2 #include <gdk/gdkkeysyms.h>
10 #include "../src/mark.h"
11 #include "../src/img.h"
12 #include "../src/yuv.h"
13 #include "../src/dir_seperator.h"
14 #include "../lib/darray.h"
15 #include "../lib/colorize.h"
16 #include "../src/process.h"
28 static int thread_debug = 0;
29 static int thread_running = 0;
30 static enum thread_preview thread_preview = PREVIEW_OFF;
32 struct colorize_priv {
35 int width, height, alpha;
41 static void colorize_destroy(GtkWidget *widget, gpointer priv)
43 struct colorize_priv *cp = (struct colorize_priv *) priv;
45 gtk_widget_destroy(cp->window);
46 g_object_unref(cp->pixbuf);
51 static gboolean colorize_key_press(GtkWidget *widget, GdkEventKey *event, gpointer priv)
53 switch (event->keyval) {
56 if (event->state & GDK_CONTROL_MASK) {
57 gtk_widget_destroy(widget);
61 ;//printf("%x\n", event->keyval);
67 static void save_event(gpointer *priv)
69 struct colorize_priv *cp = (struct colorize_priv *) priv;
71 char *filename = NULL;
74 dialog = gtk_file_chooser_dialog_new("Select file to save colorized image",
75 GTK_WINDOW(main_window),
76 GTK_FILE_CHOOSER_ACTION_SAVE,
77 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
78 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
81 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), cp->folder);
82 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), cp->filename);
83 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
84 filename = strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
87 gtk_widget_destroy(dialog);
92 if ((fp = fopen(filename, "r"))) {
95 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
96 GTK_DIALOG_DESTROY_WITH_PARENT,
98 GTK_BUTTONS_OK_CANCEL,
99 "Image already exists, overwrite it?");
100 ret = gtk_dialog_run(GTK_DIALOG (dialog));
101 gtk_widget_destroy(dialog);
102 if (ret != GTK_RESPONSE_OK)
107 save_img(cp->img, cp->width, cp->height, cp->alpha, filename, 0);
113 static void dummy_event(gpointer *priv)
117 static void close_event(gpointer *priv)
119 struct colorize_priv *cp = (struct colorize_priv *) priv;
121 gtk_widget_destroy(cp->window);
124 void colorize_image(void)
126 darray_t *gI = NULL, *cI = NULL, *I = NULL, *mI = NULL;
127 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;
129 int width = img_width, height = img_height;
130 int features, change_bc, change_alpha;
131 char *feat_names[20];
138 GtkWidget *colorize_window;
141 GtkWidget *root_menu;
143 GtkWidget *menu_item;
144 struct colorize_priv *cp;
152 /* generate grey image array */
153 dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
154 gI = darrayCreate(4, dims);
156 printerror("No memory: failed to create grey image array");
159 ptr_gI = darrayGetPr(gI);
160 img2array_short(img_grey_buffer, width, height, ptr_gI, width, height);
162 /* generade marked color image */
163 dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
164 cI = darrayCreate(4, dims);
166 printerror("No memory: failed to create marked image array");
169 ptr_cI = darrayGetPr(cI);
170 img2array_short(img_grey_buffer, width, height, ptr_cI, width, height);
171 change_bc = change_alpha = 0;
172 for (i = 0; i < height; i++) {
173 for (j = 0; j < width; j++) {
174 /* do not apply mask on index 0 */
175 c = img_mark_buffer[i*width+j];
178 /* check for any brightness/contrast change */
179 if (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1)
181 /* check for any alpha change */
182 if (mark_palette[c-1].alpha < 1)
184 /* do not apply white pixles, this meas: keep original color */
185 if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
187 ptr_cI[i*width+j] = mark_palette[c-1].r / 255.0F;
188 ptr_cI[i*width+j + width*height] = mark_palette[c-1].g / 255.0F;
189 ptr_cI[i*width+j + width*height*2] = mark_palette[c-1].b / 255.0F;
193 rc = alloc_I_arrays(&I, &mI, width, height, 1, &features, feat_names, change_alpha, change_bc);
197 set_I_ptr(I, mI, width, height, 0, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
199 // convert original image into YUV
200 rgb2yuv(ptr_gI, ptr_gI, width, height);
201 // convert maked image into YUV
202 rgb2yuv(ptr_cI, ptr_cI, width, height);
204 /* apply mask to mI */
205 for (i = 0; i < height; i++) {
206 for (j = 0; j < width; j++) {
207 /* do not apply mask on index 0 */
208 c = img_mark_buffer[i*width+j];
209 ptr_m[i*width+j] = (c == 0) ? 0.0F : 1.0F;
213 prepare_arrays(width, height, change_alpha, change_bc, img_mark_buffer, ptr_gI, ptr_cI, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, NO_TEST);
215 /* destroy temporary gI and cI */
221 /* render u and v change */
222 rc = colorize(I, mI, NULL, NULL, 5, 10, 0.01, 0, 0, feat_names, NULL);
224 printerror("No memory! Use smaller image or add more memory.");
228 postpare_arrays(width, height, change_alpha, change_bc, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, NO_TEST);
230 if (img_scale_y == img_scale_x*2)
235 /* convert YUV to RGB */
236 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height * zoom_field);
237 yuv2rgb(ptr_y, ptr_y, width, height);
239 /* private structure */
240 cp = calloc(sizeof(struct colorize_priv), 1);
243 cp->alpha = change_alpha;
245 /* apply image to be saved later */
246 cp->img = malloc(width*height*(3+change_alpha)*sizeof(unsigned short));
247 array2img_short(ptr_y, width, height, cp->img, width, height, change_alpha);
251 /* simulate alpha by pattern */
253 for (i = 0; i < height; i++) {
254 for (j = 0; j < width; j++) {
255 pat = (((j>>3)&1) == ((i>>3)&1)) ? 0.5 : 0.75;
256 a = ptr_a[i*width+j];
257 /* yuv is actually RGB */
258 ptr_y[i*width+j] = a * ptr_y[i*width+j] + (1.0 - a) * pat;
259 ptr_u[i*width+j] = a * ptr_u[i*width+j] + (1.0 - a) * pat;
260 ptr_v[i*width+j] = a * ptr_v[i*width+j] + (1.0 - a) * pat;
264 data = gdk_pixbuf_get_pixels(pixbuf);
265 rs = gdk_pixbuf_get_rowstride(pixbuf);
266 for (i = 0; i < height*zoom_field; i++) {
267 for (j = 0; j < width; j++) {
268 /* yuv is actually RGB */
269 c = ptr_y[(i/zoom_field)*width+j] * 255.0F;
274 data[i*rs + 3*j + 0] = c;
275 c = ptr_u[(i/zoom_field)*width+j] * 255.0F;
280 data[i*rs + 3*j + 1] = c;
281 c = ptr_v[(i/zoom_field)*width+j] * 255.0F;
286 data[i*rs + 3*j + 2] = c;
290 image = gtk_image_new_from_pixbuf(pixbuf);
291 gtk_widget_show(image);
298 /* during real time rendering, we cannot check if all arrays are free */
299 if (thread_preview == PREVIEW_OFF)
303 colorize_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
304 gtk_window_set_title(GTK_WINDOW(colorize_window), "Colorized");
305 g_signal_connect(colorize_window, "destroy", G_CALLBACK(colorize_destroy), cp);
306 g_signal_connect(colorize_window, "key_press_event", G_CALLBACK(colorize_key_press), cp);
308 cp->window = colorize_window;
310 p = frame_list[timeline_selected].filename;
311 while((q = strchr(p, DIR_SEPERATOR)))
313 strcpy(cp->folder, frame_list[timeline_selected].filename);
314 cp->folder[p - frame_list[timeline_selected].filename] = '\0';
315 sprintf(cp->filename, "colorized_%s", p);
318 menu_bar = gtk_menu_bar_new();
319 gtk_widget_show(menu_bar);
320 menu = gtk_menu_new();
321 root_menu = gtk_menu_item_new_with_mnemonic("_File");
322 gtk_widget_show(root_menu);
324 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE_AS, NULL);
325 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
326 g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(save_event), cp);
327 gtk_widget_show(menu_item);
328 menu_item = gtk_separator_menu_item_new();
329 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
330 g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(dummy_event), cp);
331 gtk_widget_show(menu_item);
332 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL);
333 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
334 g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(close_event), cp);
335 gtk_widget_show(menu_item);
336 gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu), menu);
337 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), root_menu);
339 /* create vbox (complete window) */
340 vbox = gtk_vbox_new(FALSE, 0);
341 gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
342 gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 2);
343 gtk_widget_show(vbox);
345 gtk_container_add(GTK_CONTAINER(colorize_window), vbox);
346 gtk_widget_show(colorize_window);
354 /* during real time rendering, we cannot check if all arrays are free */
355 if (thread_preview == PREVIEW_OFF)
359 /* real time thread */
361 static void *colorize_thread(void *arg)
363 struct colorize *col = NULL;
364 darray_t *gI = NULL, *cI = NULL, *I = NULL, *mI = NULL;
365 unsigned char *mark_buffer = NULL;
367 int features, change_bc = 0, change_alpha = 0;
368 char *feat_names[20];
373 printf("%s: thread entered\n", __func__);
377 if (thread_running < 1) {
379 printf("%s: thread leaving\n", __func__);
383 if (thread_preview == PREVIEW_NEW) {
384 thread_preview = PREVIEW_ALLOC;
387 if (thread_preview == PREVIEW_ALLOC) {
391 printf("%s: new preview\n", __func__);
395 /* alloc gI and cI array */
396 dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
397 gI = darrayCreate(4, dims);
399 printerror("No memory: failed to create grey image array");
400 thread_preview = PREVIEW_OFF;
403 dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
404 cI = darrayCreate(4, dims);
406 printerror("No memory: failed to create marked image array");
407 thread_preview = PREVIEW_OFF;
410 mark_buffer = malloc(width*height);
412 printerror("No memory: failed to create marked index image");
413 thread_preview = PREVIEW_OFF;
416 thread_preview = PREVIEW_ON;
418 if (thread_preview == PREVIEW_ON) {
420 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;
423 printf("%s: prepare gI/cI\n", __func__);
427 /* generate grey image array */
428 ptr_gI = darrayGetPr(gI);
429 img2array_short(img_grey_buffer, width, height, ptr_gI, width, height);
430 /* generade marked color image */
431 ptr_cI = darrayGetPr(cI);
432 img2array_short(img_grey_buffer, width, height, ptr_cI, width, height);
433 /* copy mark buffer */
434 memcpy(mark_buffer, img_mark_buffer, width*height);
436 /* prepare while unlocked */
438 /* apply marked pixles */
439 change_bc = change_alpha = 0;
440 for (i = 0; i < height; i++) {
441 for (j = 0; j < width; j++) {
442 /* do not apply mask on index 0 */
443 c = mark_buffer[i*width+j];
447 iterative colorization does not work with change_bc and change_alpha, because it alters I image before and after colorization
448 /* check for any brightness/contrast change */
449 if (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1)
451 /* check for any alpha change */
452 if (mark_palette[c-1].alpha < 1)
455 /* do not apply white pixles, this meas: keep original color */
456 if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
458 ptr_cI[i*width+j] = mark_palette[c-1].r / 255.0F;
459 ptr_cI[i*width+j + width*height] = mark_palette[c-1].g / 255.0F;
460 ptr_cI[i*width+j + width*height*2] = mark_palette[c-1].b / 255.0F;
464 rc = alloc_I_arrays(&I, &mI, width, height, 1, &features, feat_names, change_alpha, change_bc);
466 printerror("No memory! Use smaller image or add more memory.");
467 thread_preview = PREVIEW_OFF;
471 set_I_ptr(I, mI, width, height, 0, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
473 // convert original image into YUV
474 rgb2yuv(ptr_gI, ptr_gI, width, height);
475 // convert maked image into YUV
476 rgb2yuv(ptr_cI, ptr_cI, width, height);
478 /* apply mask to mI */
479 for (i = 0; i < height; i++) {
480 for (j = 0; j < width; j++) {
481 /* do not apply mask on index 0 */
482 c = mark_buffer[i*width+j];
483 ptr_m[i*width+j] = (c == 0) ? 0.0F : 1.0F;
487 prepare_arrays(width, height, change_alpha, change_bc, mark_buffer, ptr_gI, ptr_cI, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, NO_TEST);
489 /* prepared, so we lock */
492 if (thread_preview == PREVIEW_ON) {
494 double *ptr_gI = 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;
497 printf("%s: render preview\n", __func__);
501 /* render while unlocked */
504 set_I_ptr(I, mI, width, height, 0, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
506 /* render u and v change */
507 rc = colorize(I, mI, NULL, NULL, 1, 1, 0.0, 1, 0, feat_names, &col);
509 printerror("No memory! Use smaller image or add more memory.");
510 thread_preview = PREVIEW_OFF;
514 postpare_arrays(width, height, change_alpha, change_bc, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, NO_TEST);
516 /* convert YUV to RGB */
517 ptr_gI = darrayGetPr(gI);
518 yuv2rgb(ptr_y, ptr_gI, width, height);
522 /* simulate alpha by pattern */
524 for (i = 0; i < height; i++) {
525 for (j = 0; j < width; j++) {
526 pat = (((j>>3)&1) == ((i>>3)&1)) ? 0.5 : 0.75;
527 a = ptr_a[i*width+j];
528 ptr_gI[i*width+j] = a * ptr_gI[i*width+j] + (1.0 - a) * pat;
529 ptr_gI[i*width+j + width*height] = a * ptr_gI[i*width+j + width*height] + (1.0 - a) * pat;
530 ptr_gI[i*width+j + width*height*2] = a * ptr_gI[i*width+j + width*height*2] + (1.0 - a) * pat;
535 /* rendered, so we lock */
538 if (thread_preview == PREVIEW_ON) {
540 double *ptr_gI = NULL;
544 ptr_gI = darrayGetPr(gI);
545 array2img_short(ptr_gI, width, height, img_preview_buffer, width, height, 0);
546 draw_image(0, 0, -1, -1);
550 if (thread_preview == PREVIEW_OFF)
553 if (thread_preview == PREVIEW_FREE) {
554 thread_preview = PREVIEW_OFF;
588 int colorize_preview_init(void)
592 if (thread_running) {
593 /* we want an exit */
596 printf("%s: thread already running, terminating\n", __func__);
600 if (pthread_create(&tid, NULL, colorize_thread, NULL) < 0) {
602 printf("colorize thread creation failed!");
607 printf("%s: thread created\n", __func__);
613 void colorize_preview_terminate(void)
615 colorize_preview_free();
617 if (thread_running > 0) {
619 printf("%s: threaed is running\n", __func__);
624 printf("%s: waiting to terminate thread\n", __func__);
626 while(thread_running) {
631 printf("%s: thread is terminated\n", __func__);
634 /* indicate a new preview image */
635 void colorize_preview_alloc(void)
637 thread_preview = PREVIEW_NEW;
640 /* indicate no preview image */
641 void colorize_preview_free(void)
643 if (thread_preview != PREVIEW_OFF)
645 printf("%s: disable preview\n", __func__);
646 thread_preview = PREVIEW_FREE;