2 #include <gdk/gdkkeysyms.h>
7 #include "../src/mark.h"
9 #include "../src/opticalflow.h"
19 #include "diag_level.h"
22 #include "diag_flow.h"
25 #define CC_APP_TITLE "Colorize GTK"
26 GtkWidget *main_window;
27 GtkWidget *img_scroll;
28 GtkWidget *img_drawing_area = NULL;
29 GtkWidget *timeline_drawing_area;
30 GtkWidget *timeline_scroll;
31 GtkWidget *palette_treeview = NULL;
33 GtkToggleButton *show_marked_button, *show_highlighted_button, *show_preview_button, *show_colorized_button;
35 GtkToggleButton *show_flow_button;
37 int button_down = 0, button_down_x = -1000, button_down_y = -1000, shift_pressed = 0, ctrl_pressed = 0, button_num = 1;
38 int last_x = 0, last_y = 0; /* where mouse is over scrolled view */
40 int mark = 1, highlight = 0, preview = 0, rendered = 0, draw_mode = 1, move_mode = 0, fill_mode = 0, pick_mode = 0, flowview = 0;
41 int mouse_over_palette_area = 0, mouse_over_drawing_area = 0, mouse_over_timeline_area = 0;
42 char output_prefix[256] = "";
43 #define min(x,y) ((x < y) ? x : y)
44 #define abs(x,y) ((x < y) ? y - x : x - y)
47 void printerror(const char *fmt, ...)
53 vsprintf(buffer,fmt,args);
54 buffer[sizeof(buffer)-1]=0;
57 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
58 GTK_DIALOG_DESTROY_WITH_PARENT,
62 gtk_dialog_run (GTK_DIALOG (dialog));
63 gtk_widget_destroy (dialog);
66 static int already_destroyed = 0;
68 /* exit program and save current mask / palette */
69 void main_destroy(void)
71 if (anything_modified) {
73 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
74 GTK_DIALOG_DESTROY_WITH_PARENT,
76 GTK_BUTTONS_OK_CANCEL,
77 "Image has been changed, really quit?");
78 ret = gtk_dialog_run(GTK_DIALOG (dialog));
79 gtk_widget_destroy(dialog);
80 if (ret != GTK_RESPONSE_OK)
83 already_destroyed = 1;
88 static void destroy(GtkWidget *widget, gpointer data)
90 if (!already_destroyed)
98 /* event handler for main window keys */
99 static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
103 // if (mouse_over_palette_area)
104 if (!mouse_over_drawing_area && !mouse_over_timeline_area)
107 switch (event->keyval) {
110 if (event->state & GDK_CONTROL_MASK) {
117 frame = timeline_selected + 1;
118 if ((event->state & GDK_SHIFT_MASK) || event->keyval == GDK_Up) {
119 while(frame < timeline_frames && frame_list[frame].marked == 0 && frame_list[frame].keyframe == 0)
122 if (frame < timeline_frames)
123 timeline_select_and_save(timeline_selected, frame);
127 frame = timeline_selected - 1;
128 if ((event->state & GDK_SHIFT_MASK) || event->keyval == GDK_Down) {
129 while(frame >= 0 && frame_list[frame].marked == 0 && frame_list[frame].keyframe == 0)
133 timeline_select_and_save(timeline_selected, frame);
137 timeline_select_and_save(timeline_selected, frame);
140 frame = timeline_frames - 1;
141 timeline_select_and_save(timeline_selected, frame);
151 if (event->state & GDK_CONTROL_MASK) {
157 if (event->state & GDK_CONTROL_MASK) {
174 // printf("press %x\n", event->keyval);
180 /* event handler for main window keys */
181 static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
183 switch (event->keyval) {
193 // printf("release %x\n", event->keyval);
203 /* events if mouse is over palette area */
204 static gboolean enter_palette_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
206 mouse_over_palette_area = 1;
209 static gboolean leave_palette_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
211 mouse_over_palette_area = 0;
215 /* events if mouse is over image area */
216 static gboolean enter_drawing_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
218 mouse_over_drawing_area = 1;
221 static gboolean leave_drawing_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
223 mouse_over_drawing_area = 0;
227 /* events if mouse is over timeline area */
228 static gboolean enter_timeline_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
230 mouse_over_timeline_area = 1;
233 static gboolean leave_timeline_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
235 mouse_over_timeline_area = 0;
236 timeline_point(-1, -1);
240 /* ugly non-bresenham.... */
241 static void draw_line(int x, int y, int paint)
243 double step_x = 0, step_y = 0;
245 if (abs(x,button_down_x) > abs(y,button_down_y)) {
247 if (button_down_x < x) {
249 step_y += (double)(button_down_y - y) / (double)(button_down_x - x);
252 step_y -= (double)(button_down_y - y) / (double)(button_down_x - x);
254 paint_brush(button_down_x+step_x, button_down_y+step_y, brush_size, paint);
255 draw_image(button_down_x+step_x-(brush_size*img_scale_x/16)+1, button_down_y+step_y-(brush_size*img_scale_y/16)+1, brush_size*2*img_scale_x/16, brush_size*2*img_scale_y/16);
256 if (x == button_down_x+step_x)
261 if (y == button_down_y) /* no move at all */
263 if (button_down_y < y) {
265 step_x += (double)(button_down_x - x) / (double)(button_down_y - y);
268 step_x -= (double)(button_down_x - x) / (double)(button_down_y - y);
270 paint_brush(button_down_x+step_x, button_down_y+step_y, brush_size, paint);
271 draw_image(button_down_x+step_x-(brush_size*img_scale_x/16)+1, button_down_y+(step_y-brush_size*img_scale_y/16)+1, brush_size*2*img_scale_x/16, brush_size*2*img_scale_y/16);
272 if (y == button_down_y+step_y)
276 paint_brush(x, y, brush_size, paint);
277 draw_image(x-(brush_size*img_scale_x/16)+1, y-(brush_size*img_scale_y/16)+1, brush_size*2*img_scale_x/16, brush_size*2*img_scale_y/16);
282 /* notify movement of mouse inside image area */
283 static gint motion_notify_event( GtkWidget *widget,
284 GdkEventMotion *event )
287 GdkModifierType state;
290 gdk_window_get_pointer (event->window, &x, &y, &state);
295 state = event->state;
300 if ((state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))) {
301 if (mark || highlight) {
302 if (button_down && pick_mode) {
305 if (button_down && !pick_mode) {
307 move_mark((x-button_down_x)*16/img_scale_x, (y-button_down_y)*16/img_scale_y);
308 draw_image(0, 0, -1, -1);
311 draw_line(x, y, button_num == 1);
316 if (button_down && pick_mode)
324 /* button press event inside image area */
325 static gint button_press_event (GtkWidget *widget, GdkEventButton *event)
331 button_num = event->button;
333 if (mark || highlight) {
341 fill(x, y, event->button != 1);
342 draw_image(0, 0, -1, -1);
354 /* if not shift, draw a dot and not a line */
355 if (!shift_pressed || button_down_x == -1000) {
359 draw_line(x, y, button_num == 1);
366 static gint scroll_event (GtkWidget *widget, GdkEventScroll *event)
373 GtkAdjustment *hadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(img_scroll));
374 GtkAdjustment *vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(img_scroll));
378 printf("mouse over pixmap: %d, %d\n", x, y);
379 x -= (int)gtk_adjustment_get_value(hadjustment);
380 y -= (int)gtk_adjustment_get_value(vadjustment);
381 printf("mouse over widget: %d, %d\n", x, y);
386 GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
387 int window_width, window_height;
388 gdk_drawable_get_size (draw, &window_width, &window_height);
390 /* we need to calculate an offset, since the drawing area is now larger */
391 x -= (window_width - img_width*img_scale_x/16) / 2;
392 y -= (window_height - img_height*img_scale_y/16) / 2;
394 x = x*16/img_scale_x;
395 y = y*16/img_scale_y;
397 printf("real coordinates: %d, %d\n", x, y);
399 if (x < 0 || x >= img_width || y < 0 || y >= img_height)
406 switch (event->direction) {
410 case GDK_SCROLL_DOWN:
411 zoom_out_event(NULL);
418 /* redraw event of image area */
419 static gint img_expose_event (GtkWidget *widget, GdkEventExpose *event)
421 draw_image(event->area.x, event->area.y, event->area.width, event->area.height);
430 /* mouse move event inside timeline */
431 static gint timeline_motion_notify_event( GtkWidget *widget,
432 GdkEventMotion *event )
435 GdkModifierType state;
438 gdk_window_get_pointer (event->window, &x, &y, &state);
443 state = event->state;
446 timeline_point(x, y);
448 if ((state & GDK_BUTTON1_MASK)) {
449 timeline_clicked(x, y);
456 /* button press event inside timeline area */
457 static gint timeline_press_event (GtkWidget *widget, GdkEventButton *event)
463 timeline_clicked(x, y);
468 /* redraw event of timeline area */
469 static gint timeline_expose_event (GtkWidget *widget, GdkEventExpose *event)
471 draw_timeline(event->area.x, event->area.y, event->area.width, event->area.height);
480 GtkWidget *colorseldlg = NULL;
481 GtkColorSelection *colorsel;
482 /* color selection's buttons have been pressed */
483 void color_response(GtkDialog *dialog, gint response_id, gpointer user_data)
487 switch (response_id) {
488 case GTK_RESPONSE_CANCEL:
489 gtk_color_selection_get_previous_color(colorsel, &ncolor);
491 anything_modified = 1;
493 mark_palette[mark_selected].r = ncolor.red / 256;
494 mark_palette[mark_selected].g = ncolor.green / 256;
495 mark_palette[mark_selected].b = ncolor.blue / 256;
496 update_color(mark_selected);
497 draw_image(0, 0, -1, -1);
499 case GTK_RESPONSE_OK:
500 gtk_color_selection_get_current_color(colorsel, &ncolor);
509 /* palette entry has been clicked */
510 void palette_change(GtkTreeSelection *selection, gpointer data)
515 if (gtk_tree_selection_get_selected(selection, &model, &iter))
519 gtk_tree_model_get (model, &iter, 0/*column*/, &name, -1);
520 mark_selected = atoi(name) - 1;
526 color.red = mark_palette[mark_selected].r * 256 + 128;
527 color.green = mark_palette[mark_selected].g * 256 + 128;
528 color.blue = mark_palette[mark_selected].b * 256 + 128;
531 gtk_color_selection_set_previous_color (colorsel, &color);
532 gtk_color_selection_set_current_color (colorsel, &color);
536 /* set current color for bightness+contrast window */
539 /* set current levels in window */
542 if (highlight || preview)
543 draw_image(0, 0, -1, -1);
547 /* name of palette entry has been entered */
548 void palette_edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, GtkTreeView *treeview)
550 anything_modified = 1;
553 strncpy(mark_palette[mark_selected].name, new_text, sizeof(mark_palette[mark_selected].name));
554 mark_palette[mark_selected].name[sizeof(mark_palette[mark_selected].name)-1] = '\0';
560 model = gtk_tree_view_get_model (treeview);
561 if (gtk_tree_model_get_iter_from_string (model, &iter, path))
562 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 2/*column*/, mark_palette[mark_selected].name, -1);
565 draw_image(0, 0, -1, -1);
571 static void print_help(const char *app)
573 printf("Colorize version %s\n\n",
574 #include "../version.h"
576 printf("Usage: %s [options] [<image file>]\n", app);
577 printf(" Run colorize editor optionally with given image file.\n");
578 printf("\nOptions:\n");
579 printf(" -h --help This help\n");
580 printf(" -O --output-prefix <path>/<prefix> Store rendered image using this prefix instead of \"colorized_\"\n");
584 * command line options
586 static int handle_options(int argc, char **argv)
591 int option_index = 0, c;
592 static struct option long_options[] = {
594 {"output-prefix", 1, 0, 'O'},
598 c = getopt_long(argc, argv, "hO:", long_options, &option_index);
608 strcpy(output_prefix, optarg);
620 * creation of main window
623 int main(int argc, char *argv[])
625 GtkWidget *vbox, *tool_bar;
627 GtkWidget *pal_scroll;
629 GtkTreeSelection *selection;
630 GtkTreeViewColumn *palette_column;
631 GtkCellRenderer *palette_renderer;
634 skip_args = handle_options(argc, argv);
638 // g_thread_init(NULL); (not required, it is done automatically)
641 gtk_init(&argc, &argv);
643 main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
644 gtk_widget_set_size_request(GTK_WIDGET(main_window), 400, 200);
645 gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 500);
646 gtk_window_set_title(GTK_WINDOW(main_window), CC_APP_TITLE " Version "
647 #include "../version.h"
649 g_signal_connect(main_window, "delete-event", G_CALLBACK(destroy), NULL);
650 g_signal_connect(main_window, "destroy", G_CALLBACK(destroy), NULL);
651 g_signal_connect(main_window, "key-press-event", G_CALLBACK(on_key_press), NULL);
652 g_signal_connect(main_window, "key-release-event", G_CALLBACK(on_key_release), NULL);
655 gtk_container_set_border_width (GTK_CONTAINER (main_window), 2);
657 /* create vbox (complete window) */
658 vbox = gtk_vbox_new(FALSE, 0);
659 gtk_container_add(GTK_CONTAINER(main_window), vbox);
660 gtk_widget_show(vbox);
662 /* add menu to vbox (top of vbox) */
663 menu_bar = gtk_menu_bar_new();
664 gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
665 gtk_widget_show(menu_bar);
666 create_menus(menu_bar);
668 /* add tool_bar to vbox (bottom part of palette box) */
669 tool_bar = gtk_hbox_new(FALSE, 0);
670 gtk_box_pack_start(GTK_BOX(vbox), tool_bar, FALSE, FALSE, 2);
671 gtk_widget_show(tool_bar);
672 create_toolbar(tool_bar);
674 /* add paned view to vbox (middle part of vbox) */
675 paned = gtk_hpaned_new ();
676 gtk_widget_show(paned);
677 gtk_box_pack_start(GTK_BOX(vbox), paned, TRUE, TRUE, 2);
678 gtk_paned_set_position(GTK_PANED (paned), 250);
680 /* add palette treeview to hbox (top part of palette box) */
681 palette_treeview = gtk_tree_view_new();
682 gtk_widget_set_size_request(palette_treeview, 250, 400);
683 g_signal_connect(palette_treeview, "enter_notify_event", G_CALLBACK(enter_palette_area), NULL);
684 g_signal_connect(palette_treeview, "leave_notify_event", G_CALLBACK(leave_palette_area), NULL);
685 gtk_widget_set_events(palette_treeview, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
686 gtk_widget_show(palette_treeview);
688 pal_scroll = gtk_scrolled_window_new(NULL, NULL);
689 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pal_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
690 gtk_widget_show(pal_scroll);
691 gtk_container_add(GTK_CONTAINER(pal_scroll), palette_treeview);
693 palette_renderer = gtk_cell_renderer_text_new();
694 g_object_set(G_OBJECT(palette_renderer), "editable", FALSE, NULL);
695 palette_column = gtk_tree_view_column_new_with_attributes("", palette_renderer, "text", 0/*column*/, NULL);
696 gtk_tree_view_insert_column(GTK_TREE_VIEW(palette_treeview), GTK_TREE_VIEW_COLUMN(palette_column), 0/*column*/);
698 palette_renderer = gtk_cell_renderer_pixbuf_new();
699 palette_column = gtk_tree_view_column_new_with_attributes("", palette_renderer, "pixbuf", 1/*column*/, NULL);
700 gtk_tree_view_insert_column(GTK_TREE_VIEW(palette_treeview), GTK_TREE_VIEW_COLUMN(palette_column), 1/*column*/);
702 palette_renderer = gtk_cell_renderer_text_new();
703 g_object_set(G_OBJECT(palette_renderer), "editable", TRUE, NULL);
704 g_signal_connect(palette_renderer, "edited", (GCallback) palette_edited, palette_treeview);
705 palette_column = gtk_tree_view_column_new_with_attributes("", palette_renderer, "text", 2/*column*/, NULL);
706 gtk_tree_view_insert_column(GTK_TREE_VIEW(palette_treeview), GTK_TREE_VIEW_COLUMN(palette_column), 2/*column*/);
710 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(palette_treeview));
711 g_signal_connect(selection, "changed", G_CALLBACK(palette_change), NULL);
712 gtk_paned_pack1 (GTK_PANED (paned), pal_scroll, FALSE, TRUE);
714 /* add drawing area (right of hbox) */
715 img_drawing_area = gtk_drawing_area_new ();
716 gtk_signal_connect(GTK_OBJECT(img_drawing_area), "motion_notify_event", (GtkSignalFunc)motion_notify_event, NULL);
717 gtk_signal_connect(GTK_OBJECT (img_drawing_area), "button_press_event", (GtkSignalFunc)button_press_event, NULL);
718 gtk_signal_connect(GTK_OBJECT (img_drawing_area), "scroll_event", (GtkSignalFunc)scroll_event, NULL);
719 gtk_signal_connect(GTK_OBJECT (img_drawing_area), "expose_event", (GtkSignalFunc)img_expose_event, NULL);
720 g_signal_connect(img_drawing_area, "enter_notify_event", G_CALLBACK(enter_drawing_area), NULL);
721 g_signal_connect(img_drawing_area, "leave_notify_event", G_CALLBACK(leave_drawing_area), NULL);
722 gtk_widget_set_events(img_drawing_area, GDK_EXPOSURE_MASK
723 | GDK_ENTER_NOTIFY_MASK
724 | GDK_LEAVE_NOTIFY_MASK
725 | GDK_BUTTON_PRESS_MASK
727 | GDK_POINTER_MOTION_MASK
728 | GDK_POINTER_MOTION_HINT_MASK);
729 gtk_widget_show(img_drawing_area);
731 img_scroll = gtk_scrolled_window_new(NULL, NULL);
732 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(img_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
733 gtk_widget_show(img_scroll);
734 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(img_scroll), img_drawing_area);
735 gtk_paned_pack2 (GTK_PANED (paned), img_scroll, TRUE, TRUE);
738 /* add horizontal seperation to vbox */
739 separator = gtk_hseparator_new();
740 gtk_widget_show(separator);
741 gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 3);
744 /* add timeline (bottom of vbox) */
745 timeline_drawing_area = gtk_drawing_area_new ();
746 gtk_widget_set_size_request(timeline_drawing_area, 10, 10);
747 gtk_signal_connect(GTK_OBJECT(timeline_drawing_area), "motion_notify_event", (GtkSignalFunc)timeline_motion_notify_event, NULL);
748 gtk_signal_connect(GTK_OBJECT(timeline_drawing_area), "button_press_event", (GtkSignalFunc)timeline_press_event, NULL);
749 gtk_signal_connect(GTK_OBJECT(timeline_drawing_area), "expose_event", (GtkSignalFunc)timeline_expose_event, NULL);
750 g_signal_connect(timeline_drawing_area, "enter_notify_event", G_CALLBACK(enter_timeline_area), NULL);
751 g_signal_connect(timeline_drawing_area, "leave_notify_event", G_CALLBACK(leave_timeline_area), NULL);
752 gtk_widget_set_events(timeline_drawing_area, GDK_EXPOSURE_MASK
753 | GDK_ENTER_NOTIFY_MASK
754 | GDK_LEAVE_NOTIFY_MASK
755 | GDK_BUTTON_PRESS_MASK
756 | GDK_POINTER_MOTION_MASK
757 | GDK_POINTER_MOTION_HINT_MASK);
758 gtk_widget_show(timeline_drawing_area);
759 timeline_scroll = gtk_scrolled_window_new(NULL, NULL);
760 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(timeline_scroll), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
761 // gtk_widget_show(timeline_scroll);
762 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(timeline_scroll), timeline_drawing_area);
763 gtk_box_pack_start(GTK_BOX(vbox), timeline_scroll, FALSE, FALSE, 0);
765 create_timeline(NULL);
768 img_label = GTK_LABEL(gtk_label_new(NULL));
769 gtk_widget_show(GTK_WIDGET(img_label));
770 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(img_label), FALSE, FALSE, 0);
773 gtk_widget_show(main_window);
775 /* enable some button/menu */
776 set_menu_toggel_by_label(TOGGLE_LABEL_MARK, mark);
777 set_button_toggel_by_label(TOGGLE_LABEL_MARK, mark);
780 create_timeline(argv[1]);
782 create_image(frame_list[timeline_selected].filename, 1);
785 colorize_preview_init();
787 colorize_preview_terminate();