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