Add option to keep I and mI arrays and "neighbor pixle weights" structure
[colorize.git] / src / colorize.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <getopt.h>
6 #include <math.h>
7 #include <time.h>
8 #include "../lib/darray.h"
9 #include "../lib/colorize.h"
10 #include "img.h"
11 #include "yuv.h"
12 #include "mark.h"
13 #include "process.h"
14 #include "dir_seperator.h"
15 #ifdef WITH_OPENCV
16 #include "opticalflow.h"
17 #endif
18
19 static void print_help(const char *app);
20 static void print_test_help();
21
22 //#defbug SEQUENCE
23 //#define SINGLE_K_TEST 2
24
25 /*
26  * load sequence
27  */
28
29 struct sequence {
30         char filename[256];
31 };
32 static struct sequence *sequence = NULL;
33
34 /* load sequence list and return number of images in sequence */
35 static int load_sequence(int *start, int *next, char *first_filename)
36 {
37         const char *name = "sequence";
38         int count;
39         int i, j, keyframe_before_start, eof;
40         FILE *fp;
41         char buffer[256], *p;
42
43         /* free previously used sequence */
44         if (sequence)
45                 free(sequence);
46         sequence = NULL;
47
48 again:
49         /* get number of frames until next keyframe or end of squence */
50         fp = fopen(name, "r");
51         if (!fp) {
52                 printf("failed to load sequence '%s'\n", name);
53                 return -1;
54         }
55         count = 0;
56         j = 0;
57         eof = 1;
58         keyframe_before_start = 0;
59         while(fgets(buffer, sizeof(buffer), fp)) {
60                 p = strchr(buffer + 1, '\"');
61                 if (!p)
62                         break;
63                 *p = '\0';
64                 if (j == 0)
65                         strcpy(first_filename, buffer + 1);
66                 p++;
67                 if ((*start) && j == (*start) - 1) {
68                         if (strstr(p, "keyframe"))
69                                 keyframe_before_start = 1;
70                 }
71                 if (j < (*start)) {
72                         j++;
73                         continue;
74                 }
75 #ifdef DEBUG_SEQUENCE
76                 printf("counting %d\n", j);
77 #endif
78                 j++;
79                 count++;
80                 /* skip start frame, since it is always a keyframe */
81                 if (count == 1)
82                         continue;
83                 if (strstr(p, "keyframe")) {
84                         eof = 0;
85                         break;
86                 }
87         }
88         fclose(fp);
89
90         /* end of file case */
91         if (count == 0) {
92 #ifdef DEBUG_SEQUENCE
93                 puts("end of file");
94 #endif
95                 *next = -1;
96                 return 0;
97         } else
98         if (count == 1) {
99 #ifdef DEBUG_SEQUENCE
100                 puts("count=1");
101 #endif
102                 if (eof) {
103 #ifdef DEBUG_SEQUENCE
104                         puts("end of file at last frame");
105 #endif
106                         *next = -1;
107                         return 0;
108                 }
109                 /* we are done, because we already had the last sequence */
110                 if (!keyframe_before_start) {
111 #ifdef DEBUG_SEQUENCE
112                         puts("no keyframe before start");
113 #endif
114                         (*next) = -1;
115                         return 0;
116                 }
117 #ifdef DEBUG_SEQUENCE
118                 puts("keyframe before start");
119 #endif
120                 /* we just have a single last frame */
121                 count = 1;
122                 (*next) = (*start) + 1;
123         } else
124         /* if we have two keyframes side by side, we ignore it */
125         if (count == 2 && !eof) {
126 #ifdef DEBUG_SEQUENCE
127                 puts("count=2");
128 #endif
129                 /* only if the frame before start is not a keyframe
130                  * and we are not the first sequence, because that would mean
131                  * that the first frame is a single sequence */
132                 if (!keyframe_before_start && (*start) > 0) {
133 #ifdef DEBUG_SEQUENCE
134                         puts("no keyframe before start");
135 #endif
136                         (*start)++;
137                         goto again;
138                 }
139 #ifdef DEBUG_SEQUENCE
140                 puts("keyframe before start or first frame");
141 #endif
142                 /* now the start frame has one keyframe before and one after */
143                 count = 1;
144                 (*next) = (*start) + 1;
145         } else {
146                 (*next) = (*start) + count - 1;
147         }
148
149         /* alloc memory for sequence and fill with data */
150         sequence = (struct sequence *)malloc(sizeof(struct sequence) * count);
151         if (!sequence) {
152                 printf("no memory for sequence\n");
153                 return -1;
154         }
155         memset((struct sequence *)sequence, 0, sizeof(struct sequence) * count);
156         fp = fopen(name, "r");
157         if (!fp) {
158                 printf("failed to load sequence '%s'\n", name);
159                 return -1;
160         }
161         i = 0;
162         j = 0;
163         while(fgets(buffer, sizeof(buffer), fp)) {
164                 p = strchr(buffer + 1, '\"');
165                 if (!p)
166                         break;
167                 if (j < (*start)) {
168                         j++;
169                         continue;
170                 }
171                 *p = '\0';
172                 strcpy(sequence[i].filename, buffer + 1);
173                 i++;
174                 if (i == count)
175                         break;
176         }
177         fclose(fp);
178
179         return count;
180 }
181
182 /*
183  * options
184  */
185
186 static int in_itr_num = 5, out_itr_num = 1, quick = 0, optical_flow = 1, bright_contrast = 1, alpha_change = 1;
187 int scale = 1, scalexyz = 999;
188
189 static enum test test = NO_TEST;
190
191 static int parse_test(const char *arg)
192 {
193         if (!strcmp(arg, "help")) {
194                 print_test_help();
195                 exit(0);
196         }
197 #ifdef WITH_OPENCV
198         if (!strcmp(arg, "flow-next"))
199                 return FLOW_NEXT;
200         if (!strcmp(arg, "flow-prev"))
201                 return FLOW_PREV;
202 #endif
203         if (!strcmp(arg, "marked"))
204                 return MARKED;
205         if (!strcmp(arg, "mask"))
206                 return MASK;
207         if (!strcmp(arg, "mask+color"))
208                 return MASK_COLOR;
209         if (!strcmp(arg, "bc-only"))
210                 return BC_ONLY;
211         if (!strcmp(arg, "bc-image"))
212                 return BC_IMAGE;
213         if (!strcmp(arg, "alpha"))
214                 return ALPHA;
215         if (!strcmp(arg, "no-alpha"))
216                 return NO_ALPHA;
217         if (!strcmp(arg, "removal-image"))
218                 return REMOVAL_IMAGE;
219
220         return NO_TEST;
221 }
222
223 static int handle_options(int argc, char **argv)
224 {
225         int skip_args = 0;
226
227         while (1) {
228                 int option_index = 0, c;
229                 static struct option long_options[] = {
230                         {"help", 0, 0, 'h'},
231                         {"depth", 1, 0, 'd'},
232                         {"in-itr-num", 1, 0, 'i'},
233                         {"out-itr-num", 1, 0, 'o'},
234                         {"quick", 0, 0, 'q'},
235                         {"zscale", 1, 0, 'z'},
236                         {"brightness-contrast", 1, 0, 'b'},
237                         {"optical-flow", 1, 0, 'f'},
238                         {"scale", 1, 0, 's'},
239                         {"test", 1, 0, 't'},
240                         {0, 0, 0, 0},
241                 };
242
243                 c = getopt_long(argc, argv, "hd:i:o:qz:b:f:s:t:", long_options, &option_index);
244
245                 if (c == -1)
246                         break;
247
248                 switch (c) {
249                 case 'h':
250                         print_help(argv[0]);
251                         exit(0);
252                 case 'd':
253                         save_depth = atoi(optarg);
254                         skip_args += 2;
255                         break;
256                 case 'i':
257                         in_itr_num = atoi(optarg);
258                         skip_args += 2;
259                         break;
260                 case 'o':
261                         out_itr_num = atoi(optarg);
262                         skip_args += 2;
263                         break;
264                 case 'q':
265                         quick = 1;
266                         skip_args += 1;
267                         break;
268                 case 'z':
269                         scalexyz = atoi(optarg);
270                         skip_args += 2;
271                         break;
272                 case 'b':
273                         bright_contrast = atoi(optarg);
274                         skip_args += 2;
275                         break;
276                 case 'a':
277                         alpha_change = atoi(optarg);
278                         skip_args += 2;
279                         break;
280                 case 'f':
281                         optical_flow = atoi(optarg);
282                         skip_args += 2;
283                         break;
284                 case 's':
285                         scale = atoi(optarg);
286                         skip_args += 2;
287                         break;
288                 case 't':
289                         test = parse_test(optarg);
290                         if (!test) {
291                                 fprintf(stderr, "Invalid test '%s', use '--test help' to get a list of tests\n", optarg);
292                                 exit(-1);
293                         }
294                         skip_args += 2;
295                         break;
296                 default:
297                         break;
298                 }
299         }
300
301         return skip_args;
302 }
303
304 /*
305  * usage
306  */
307
308 static void print_help(const char *app)
309 {
310         printf("Colorize version %s\n\n",
311 #include "../version.h"
312         );
313         printf("Usage: %s [options] <grey ppm image> <marked ppm image> <result ppm image> [<frames> <start>]\n", app);
314         printf("       Colorize grey image using marked image and save to result image.\n");
315         printf("       If frames and start frame is given, image names must include printf integer formatting (e.g. %%04d).\n");
316         printf("Usage: %s [options] <grey ppm image> marked <result ppm image>\n", app);
317         printf("       Colorize grey image using marked mask + palette and save to result image.\n");
318         printf("Usage: %s [options] sequence [list | <start with frame> [<stop with frame>]]\n", app);
319         printf("       Colorize movie sequence (generated by colorize gui) as found in the current directory.\n");
320         printf("       Use list to view sequence segments between keyframes.\n");
321         printf("\nOptions:\n");
322         printf(" -h --help                           This help\n");
323         printf(" -d --depth <bits>                   Save images with given color bit depth (default=%d)\n", save_depth);
324         printf(" -i --in-itr-num <num>               Alter inner iterations (weightening count) of colorization algorithm (default=%d)\n", in_itr_num);
325         printf(" -o --out-itr-num <num>              Alter outer iterations (complete turns) of colorization algorithm (default=%d)\n", out_itr_num);
326         printf(" -q --quick                          Use quick render, but sufaces may be colorized incomplete\n");
327         printf(" -z --zscale <levels>                How many grids (staring with the finest) should be scaled in z direction to generate the next coarse grid ");
328         if (scalexyz < 999)
329                 printf("(default=%d)\n", scalexyz);
330         else
331                 printf("(default=infinite)\n");
332         printf(" -b --brightness-contrast [0 | 1]    Apply brightnes and contrast, if defined in palette by GUI (default=%d)\n", bright_contrast);
333         printf(" -a --alpha-change [0 | 1]           Apply alpha channel change, if defined in palette by GUI (default=%d)\n", alpha_change);
334 #ifdef WITH_OPENCV
335         printf(" -f --optical-flow [0 | 1]           Apply optical flow, if defined by GUI (default=%d)\n", optical_flow);
336 #endif
337         printf(" -s --scale [1..n]                   Scale down by the given factor for quick and dirty previews (default=%d)\n", scale);
338         printf(" -t --test <test>                    Generate test images. Use 'help' for list of tests\n");
339 }
340
341 static void print_test_help()
342 {
343         printf(" -t --test <test>        Generate test images...\n");
344 #ifdef WITH_OPENCV
345         printf("           flow-next     Optical flow plane to next image\n");
346         printf("           flow-prev     Optical flow plane to previous image\n");
347 #endif
348         printf("           marked        Only apply marked colors to grey image\n");
349         printf("           mask          Show mask of marked areas\n");
350         printf("           mask+color    Show mask of marked areas + color\n");
351         printf("           bc-only       Only apply brightness+contrast, leave colors of grey image as is\n");
352         printf("           bc-image      Show brightness+contrast change on grey image as uv components\n");
353         printf("           alpha         Show the image with alpha channel only\n");
354         printf("           no-alpha      Show the image without alpha channel, to see pixles that are made transparent\n");
355         printf("           removal-image Show the image with \"transparency removal layer\" only, but keep u and v\n");
356 }
357
358 /*
359  * main function
360  */
361
362 int main(int argc, char *argv[])
363 {
364         darray_t *gI = NULL, *cI = NULL, *mI = NULL, *I = NULL;
365         darray_t *flow = NULL, *flow_i = NULL;
366         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;
367         double diff, sum;
368         int dims[4];
369         int w = 0, h = 0, load_w, load_h, k = 1, index = 0, z;
370         unsigned short *img = NULL;
371         unsigned char *mark_buffer = NULL;
372         int rc, x, y, i, ii;
373         time_t start, end;
374         const char* filename;
375         char first_filename[256];
376         int seq_offset = 0, seq_next = 0;
377         int features, change_bc, change_alpha;
378         char *feat_names[20];
379         int skip_args;
380
381         skip_args = handle_options(argc, argv);
382         argc -= skip_args;
383         argv += skip_args;
384
385         if (argc <= 1) {
386                 print_help(argv[0]);
387                 return 0;
388         }
389
390 next_sequence:
391         if (argc > 1 && !strcmp(argv[1], "sequence")) {
392                 k = load_sequence(&seq_offset, &seq_next, first_filename);
393                 if (k == 0)
394                         return 0;
395                 printf("Got %d frames from sequence (frames %d..%d)\n", k, seq_offset, seq_offset + k - 1);
396                 if (argc > 2 && (!strcmp(argv[2], "list") || atoi(argv[2]) > seq_offset)) {
397                         seq_offset = seq_next;
398                         goto next_sequence;
399                 }
400         } else if (argc <= 3) {
401                 print_help(argv[0]);
402                 return 0;
403         } else if (argc > 5) {
404                 k = atoi(argv[4]);
405                 index = atoi(argv[5]);
406         }
407         if (k <= 0)
408                 return 0;
409
410 #ifdef SINGLE_K_TEST
411         if (k > SINGLE_K_TEST)
412                 k = SINGLE_K_TEST;
413 #endif
414
415         time(&start);
416
417         change_bc = change_alpha = 0;
418         for (z = 0; z < k; z++) {
419                 if (sequence) {
420                         filename = sequence[z].filename;
421                         /* first_filename is set by load_sequence */
422                 } else {
423                         filename = argv[1];
424                         strcpy(first_filename, argv[1]);
425                 }
426 #ifdef WITH_OPENCV
427                 // load flow settings
428                 if (sequence && optical_flow) {
429                         flow_default();
430                         load_flow(first_filename);
431                         if (flow_enable == 0 && (test == FLOW_NEXT || test == FLOW_PREV)) {
432                                 fprintf(stderr, "Cannot test optical flow, because it is not enabled by GUI.\n");
433                                 exit (0);
434                         }
435                 }
436 #endif
437                 // load original image and convert their RGB components to double RGB array
438                 img = load_img(&load_w, &load_h, filename, index + z);
439                 if (!img) {
440                         fprintf(stderr, "Failed to load grey image '%s'\n", filename);
441                         return 0;
442                 }
443                 scale_img(img, load_w, load_h, scale);
444                 if (z == 0) {
445                         w = load_w / scale;
446                         h = load_h / scale;
447                 }
448                 if (load_w/scale != w || load_h/scale != h) {
449                         fprintf(stderr, "Error: All input images must have equal dimenstions.\n");
450                         return 0;
451                 }
452                 // now we know the dimensions, so we can create input arrays
453                 if (!gI) {
454                         dims[0] = w; dims[1] = h; dims[2] = 3; dims[3] = k;
455                         gI = darrayCreate(4, dims);
456                 }
457                 if (!gI) {
458                         printf("failed to create grey image array\n");
459                         exit (0);
460                 }
461                 if (!cI) {
462                         dims[0] = w; dims[1] = h; dims[2] = 3; dims[3] = k;
463                         cI = darrayCreate(4, dims);
464                 }
465                 if (!cI) {
466                         printf("failed to create marked image array\n");
467                         exit (0);
468                 }
469                 img2array_short(img, w, h, darrayGetPr(gI) + w*h*3*z, w, h);
470                 free(img);
471
472                 if (sequence || !strcmp(argv[2], "marked")) {
473                         char name[256];
474                         unsigned char c;
475                         // load marked mask and convert their RGB components to double YUV array
476                         memcpy(darrayGetPr(cI) + w*h*3*z, darrayGetPr(gI) + w*h*3*z, w*h*3 * sizeof(double));
477                         /* add extra memory for unscaled data to prevent buffer overflow */
478                         if (!mark_buffer)
479                                 mark_buffer = (unsigned char *)malloc(w*h*k + load_w*load_h);
480                         if (!mark_buffer) {
481                                 printf("no memory for mark buffer\n");
482                                 exit (0);
483                         }
484                         if (load_palette(first_filename)) {
485                                 printf("failed to load palette for file: '%s'\n", filename);
486                                 exit (0);
487                         }
488                         sprintf(name, filename, index + z);
489                         /* always load full unscaled image, then scale down */
490                         if (load_marked(mark_buffer + w*h*z, load_w, load_h, name) == 0) {
491                                 scale_mark(mark_buffer + w*h*z, load_w, load_h, scale);
492                                 ptr_cI = darrayGetPr(cI) + w*h*3*z;
493                                 for (y = 0; y < h; y++) {
494                                         for (x = 0; x < w; x++) {
495                                                 /* do not apply mask on index 0 */
496                                                 c = mark_buffer[y*w+x + w*h*z];
497                                                 if (c == 0)
498                                                         continue;
499                                                 /* check for any brightness/contrast change */
500                                                 if (bright_contrast && (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1))
501                                                         change_bc = 1;
502                                                 /* check for any alpha change */
503                                                 if (alpha_change && mark_palette[c-1].alpha < 1)
504                                                         change_alpha = 1;
505                                                 /* do not apply white pixles, this meas: keep original color */
506                                                 if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
507                                                         continue;
508                                                 ptr_cI[y*w+x] = mark_palette[c-1].r / 255.0F;
509                                                 ptr_cI[y*w+x + w*h] = mark_palette[c-1].g / 255.0F;
510                                                 ptr_cI[y*w+x + w*h*2] = mark_palette[c-1].b / 255.0F;
511                                         }
512                                 }
513                         } else
514                                 memset(mark_buffer + w*h*z, 0, w*h);
515                 } else {
516                         // load marked image and convert their RGB components to double YUV array
517                         img = load_img(&load_w, &load_h, argv[2], index + z);
518                         if (!img) {
519                                 scale_img(img, load_w, load_h, scale);
520                                 if (load_w/scale != w || load_h/scale != h) {
521                                         fprintf(stderr, "Error: All input images must have equal dimenstions.\n");
522                                         return 0;
523                                 }
524                                 img2array_short(img, w, h, darrayGetPr(cI) + w*h*3*z, w, h);
525                                 free(img);
526                         } else {
527                                 fprintf(stderr, "Failed to load marked image, omitting...\n");
528                                 memcpy(darrayGetPr(cI) + w*h*3*z, darrayGetPr(gI) + w*h*3*z, w*h*3 * sizeof(double));
529                         }
530                 }
531         }
532
533         rc = alloc_I_arrays(&I, &mI, w, h, k, &features, feat_names, change_alpha, change_bc);
534         if (rc)
535                 exit(0);
536
537         for (z = 0; z < k; z++) {
538                 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);
539                 ptr_gI = darrayGetPr(gI) + w*h*3*z;
540                 ptr_cI = darrayGetPr(cI) + w*h*3*z;
541
542                 // convert original image into YUV
543                 rgb2yuv(ptr_gI, ptr_gI, w, h);
544                 // convert maked image into YUV
545                 rgb2yuv(ptr_cI, ptr_cI, w, h);
546
547                 if (sequence || !strcmp(argv[2], "marked")) {
548                         unsigned char c;
549                         // use marked mask to fill markIm
550                         for (y = 0; y < h; y++) {
551                                 for (x = 0; x < w; x++) {
552                                         /* do not apply mask on index 0 */
553                                         c = mark_buffer[y*w+x + w*h*z];
554                                         if (c)
555                                                 ptr_m[y*w+x] = 1.0F;
556                                         else
557                                                 ptr_m[y*w+x] = 0.0F;
558                                 }
559                         }
560                 } else {
561                         // fill color image with marked pixles
562                         // - calculate the difference between two images (original image - color image)
563                         // - convert into absolute (positive values)
564                         // - sum all components to get grey image
565                         // - apply threshold (pixle is 1F, if the absolute difference is > 0.01F)
566                         // original code: markIm=(sum(abs(gI-cI),3)>0.01); (according to developers of the algorithm)
567                         for (i = 0, ii = w * h; i < ii; i++) {
568                                 diff = 0;
569                                 sum = ptr_gI[i] - ptr_cI[i];
570                                 if (sum < 0)
571                                         diff -= sum;
572                                 else
573                                         diff += sum;
574                                 sum = ptr_gI[i + ii] - ptr_cI[i + ii];
575                                 if (sum < 0)
576                                         diff -= sum;
577                                 else
578                                         diff += sum;
579                                 sum = ptr_gI[i + ii + ii] - ptr_cI[i + ii + ii];
580                                 if (sum < 0)
581                                         diff -= sum;
582                                 else
583                                         diff += sum;
584                                 if (diff > 0.01)
585                                         ptr_m[i] = 1.0;
586                                 else
587                                         ptr_m[i] = 0.0;
588                         }
589                 }
590
591                 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);
592         }
593
594 #ifdef WITH_OPENCV
595         if (k > 1 && flow_enable) {
596                 /* create flow vectors */
597                 dims[0] = w; dims[1] = h; dims[2] = k - 1; dims[3] = 2;
598                 flow = darrayCreate(4, dims);
599                 if (!flow) {
600                         printf("failed to create array\n");
601                         exit (0);
602                 }
603                 flow_i = darrayCreate(4, dims);
604                 if (!flow_i) {
605                         printf("failed to create array\n");
606                         exit (0);
607                 }
608                 printf("Calculating optical flow for %d frames: window=%d\n", k, flow_window/scale);
609         } else if (k > 1)
610                 printf("Note: Optical flow is not activated!\n");
611         for (z = 0; z < k-1; z++) {
612                 if (flow)
613                         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);
614                 if (flow_i)
615                         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);
616         }
617 #else
618         if (k > 1)
619                 printf("Note: Optical flow is not compiled in!\n");
620 #endif
621
622         darrayDestroy(gI);
623         gI = NULL;
624         darrayDestroy(cI);
625         cI = NULL;
626
627         if (test != FLOW_NEXT && test != FLOW_PREV && test != MARKED && test != MASK && test != MASK_COLOR && test != BC_ONLY && test != BC_IMAGE) {
628                 printf("Colorizing %d frames, please wait...\n", k);
629                 rc = colorize(I, mI, flow, flow_i, in_itr_num, out_itr_num, quick, scalexyz, feat_names, NULL);
630                 if (rc < 0) {
631                         if (k > 1)
632                                 printf("No memory! Use smaller frames or less frames between key frames or add more memory.");
633                         else
634                                 printf("No memory! Use smaller image or add more memory.");
635                         exit(-1);
636                 }
637         }
638
639         for (z = 0; z < k; z++) {
640                 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);
641                 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);
642
643 #ifdef WITH_OPENCV
644                 if (test == FLOW_NEXT || test == FLOW_PREV) {
645                         double *ptr_f1 = NULL, *ptr_f2 = NULL;
646                         /* apply flow planes to result image as u and y vector */
647                         if (test == FLOW_NEXT) {
648                                 if (flow) {
649                                         ptr_f1 = darrayGetPr(flow) + w*h*z;
650                                         ptr_f2 = darrayGetPr(flow) + w*h*z*(k-1);
651                                 }
652                         } else {
653                                 if (flow_i) {
654                                         ptr_f1 = darrayGetPr(flow_i) + w*h*z;
655                                         ptr_f2 = darrayGetPr(flow_i) + w*h*z*(k-1);
656                                 }
657                         }
658                         if (ptr_f1 && ptr_f1) {
659                                 for (y = 0; y < h; y++) {
660                                         for (x = 0; x < w; x++) {
661                                                 ptr_y[w*y+x] = 0.5;
662                                                 if (z < k-1) {
663                                                         ptr_u[w*y+x] = ptr_f1[w * y + x] / 50;
664                                                         ptr_v[w*y+x] = ptr_f2[w * y + x] / 50;
665                                                 } else {
666                                                         ptr_u[w*y+x] = 0;
667                                                         ptr_v[w*y+x] = 0;
668                                                 }
669                                         }
670                                 }
671                         }
672                 }
673 #endif
674
675                 // save result YUV array to image with RGB components
676                 yuv2rgb(ptr_y, ptr_y, w, h);
677                 if (sequence) {
678                         static char name[256], *p, *q;
679                         p = sequence[z].filename;
680                         while((q = strchr(p, DIR_SEPERATOR)))
681                                 p = q + 1;
682                         strcpy(name, sequence[z].filename);
683                         name[p - sequence[z].filename] = '\0';
684                         strcat(name, "colorized_");
685                         strcat(name, p);
686                         filename = name;
687                 } else
688                         filename = argv[3];
689                 /* don't save alpha on these tests */
690                 if (test == ALPHA || test == REMOVAL_IMAGE || test == NO_ALPHA)
691                         save_img_array(ptr_y, w, h, 0, filename, index + z);
692                 else
693                         save_img_array(ptr_y, w, h, change_alpha, filename, index + z);
694         }
695
696         time(&end);
697         printf("Elapsed time: %d minutes, %d seconds\n", (int)(end-start)/60, (int)(end-start)%60);
698
699         // destroy
700         darrayDestroy(I);
701         I = NULL;
702         darrayDestroy(mI);
703         mI = NULL;
704         darrayDestroy(flow);
705         flow = NULL;
706         darrayDestroy(flow_i);
707         flow_i = NULL;
708
709         free(mark_buffer);
710         mark_buffer = NULL;
711
712         darrayDone();
713
714 #ifdef SINGLE_K_TEST
715         exit(0);
716 #endif
717         if (sequence) {
718                 /* if end frame is not given or if not reached */
719                 if (argc <= 3 || atoi(argv[3]) > seq_offset + k) {
720                         seq_offset = seq_offset + k - 1;
721                         goto next_sequence;
722                 }
723         }
724
725         return 0;
726 }
727