Version 0.3
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 9 Aug 2014 06:10:29 +0000 (08:10 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 15 Mar 2015 14:33:52 +0000 (15:33 +0100)
- 16 bit color depth support
- new YUV color model without fading saturation on brightness change
- various fixes

17 files changed:
doc/documentation.odt
gui/colorize.c
gui/image.c
gui/image.h
gui/level.c
gui/main.c
gui/timeline.c
src/colorize.c
src/mark.c
src/opticalflow.c
src/opticalflow.h
src/ppm.c
src/ppm.h
src/yuv.c
src/yuv.h
tools/fields.c
version.h

index 2c4855b..f1890c6 100644 (file)
Binary files a/doc/documentation.odt and b/doc/documentation.odt differ
index 61d396d..61e6345 100644 (file)
@@ -56,7 +56,7 @@ static void save_event(gpointer *priv)
        struct colorize_priv *cp = (struct colorize_priv *) priv;
        guchar *data;
        int rs, i, j;
        struct colorize_priv *cp = (struct colorize_priv *) priv;
        guchar *data;
        int rs, i, j;
-       unsigned char *buffer;
+       unsigned short *buffer;
        GtkWidget *dialog;
        char *filename = NULL;
 
        GtkWidget *dialog;
        char *filename = NULL;
 
@@ -80,13 +80,13 @@ static void save_event(gpointer *priv)
 
        data = gdk_pixbuf_get_pixels(cp->pixbuf);
         rs = gdk_pixbuf_get_rowstride(cp->pixbuf);
 
        data = gdk_pixbuf_get_pixels(cp->pixbuf);
         rs = gdk_pixbuf_get_rowstride(cp->pixbuf);
-       buffer = malloc(cp->width*cp->height*3);
+       buffer = malloc(cp->width*cp->height*3*sizeof(unsigned short));
 
        for (i = 0; i < cp->height; i++) {
                for (j = 0; j < cp->width; j++) {
 
        for (i = 0; i < cp->height; i++) {
                for (j = 0; j < cp->width; j++) {
-                       buffer[(i*cp->width+j)*3+0] = data[i*rs+j*3+0];
-                       buffer[(i*cp->width+j)*3+1] = data[i*rs+j*3+1];
-                       buffer[(i*cp->width+j)*3+2] = data[i*rs+j*3+2];
+                       buffer[(i*cp->width+j)*3+0] = data[i*rs+j*3+0] << 8;
+                       buffer[(i*cp->width+j)*3+1] = data[i*rs+j*3+1] << 8;
+                       buffer[(i*cp->width+j)*3+2] = data[i*rs+j*3+2] << 8;
                }
        }
 
                }
        }
 
index 1590279..258a377 100644 (file)
@@ -18,7 +18,7 @@ GdkPixbuf *img_pixbuf = NULL;
 int img_width, img_height;
 int copy_width, copy_height;
 char img_name[256];
 int img_width, img_height;
 int copy_width, copy_height;
 char img_name[256];
-unsigned char *img_grey_buffer = NULL;
+unsigned short *img_grey_buffer = NULL;
 unsigned char *img_mark_buffer = NULL, *img_mark_buffer_undo[UNDO_MAX], *img_mark_buffer_copy;
 int button_down_x_undo[UNDO_MAX], button_down_y_undo[UNDO_MAX];
 int undo_current, undo_num;
 unsigned char *img_mark_buffer = NULL, *img_mark_buffer_undo[UNDO_MAX], *img_mark_buffer_copy;
 int button_down_x_undo[UNDO_MAX], button_down_y_undo[UNDO_MAX];
 int undo_current, undo_num;
@@ -27,7 +27,7 @@ int anything_modified;
 extern int button_down_x, button_down_y;
 
 /* load image and create pixbuf */
 extern int button_down_x, button_down_y;
 
 /* load image and create pixbuf */
-void create_image(const char *filename)
+void create_image(const char *filename, int resize)
 {
        int rc;
        static char imgfile[256];
 {
        int rc;
        static char imgfile[256];
@@ -78,7 +78,7 @@ void create_image(const char *filename)
 
 no_mark:
        /* create pixbuf */
 
 no_mark:
        /* create pixbuf */
-       create_or_reset_pixbuf(1);
+       create_or_reset_pixbuf(resize);
 }
 
 void create_or_reset_pixbuf(int resize)
 }
 
 void create_or_reset_pixbuf(int resize)
@@ -87,21 +87,25 @@ void create_or_reset_pixbuf(int resize)
        GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(main_window));
        GdkRectangle max;
 
        GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(main_window));
        GdkRectangle max;
 
-       /* calculate the maximum windows size, so that the border will not exceed the screen size */
-       gdk_window_get_frame_extents(gtk_widget_get_window(main_window), &max);
-       max.width -= main_window->allocation.width;
-       max.height -= main_window->allocation.height;
-       if (max.width < 0)
-               max.width = 0;
-       if (max.height < 0)
-               max.height = 0;
-       max.width = gdk_screen_get_width(screen)-max.width;
-       max.height = gdk_screen_get_height(screen)-max.height;
-
        if (resize && screen) {
        if (resize && screen) {
+               /* process GTK window event to have correct size */
+               while (gtk_events_pending())
+                       gtk_main_iteration();
+
+               /* calculate the maximum windows size, so that the border will not exceed the screen size */
+               gdk_window_get_frame_extents(gtk_widget_get_window(main_window), &max);
+               max.width -= main_window->allocation.width;
+               max.height -= main_window->allocation.height;
+               if (max.width < 0)
+                       max.width = 0;
+               if (max.height < 0)
+                       max.height = 0;
+               max.width = gdk_screen_get_width(screen)-max.width;
+               max.height = gdk_screen_get_height(screen)-max.height;
+
 try_smaller:
 try_smaller:
-               w = img_scroll->allocation.width-20;
-               h = img_scroll->allocation.height-20;
+               w = img_scroll->allocation.width-25;
+               h = img_scroll->allocation.height-25;
                if (w < img_width*img_scale_x/16) {
                        w = main_window->allocation.width - w + img_width*img_scale_x/16;
                        if (w > max.width) {
                if (w < img_width*img_scale_x/16) {
                        w = main_window->allocation.width - w + img_width*img_scale_x/16;
                        if (w > max.width) {
@@ -273,9 +277,9 @@ void draw_image(int x, int y, int w, int h)
                        for (j = 0; j < w; j++) {
                                if (preview && !rendered && !flowview) {
                                        /* apply selected color from palette to all pixles */
                        for (j = 0; j < w; j++) {
                                if (preview && !rendered && !flowview) {
                                        /* apply selected color from palette to all pixles */
-                                       _r = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] / 255.0F;
-                                       _g = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] / 255.0F;
-                                       _b = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] / 255.0F;
+                                       _r = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] / 65535.0F;
+                                       _g = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] / 65535.0F;
+                                       _b = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] / 65535.0F;
                                        rgb2yuv_pixle(_r, _g, _b, &_y, &_u, &_v);
                                        _y = (_y - 0.5) * mark_palette[mark_selected].contrast + 0.5;
                                        _y += mark_palette[mark_selected].bright;
                                        rgb2yuv_pixle(_r, _g, _b, &_y, &_u, &_v);
                                        _y = (_y - 0.5) * mark_palette[mark_selected].contrast + 0.5;
                                        _y += mark_palette[mark_selected].bright;
@@ -307,9 +311,9 @@ void draw_image(int x, int y, int w, int h)
                                        compose[j*3+2] = _c;
 
                                } else {
                                        compose[j*3+2] = _c;
 
                                } else {
-                                       compose[j*3] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3];
-                                       compose[j*3+1] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1];
-                                       compose[j*3+2] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2];
+                                       compose[j*3] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] >> 8;
+                                       compose[j*3+1] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] >> 8;
+                                       compose[j*3+2] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] >> 8;
                                }
                                c = img_mark_buffer[(j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y)];
                                if (c > 0 && !flowview && !(rendered && preview)) {
                                }
                                c = img_mark_buffer[(j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y)];
                                if (c > 0 && !flowview && !(rendered && preview)) {
index 59b4b4a..c66b2d9 100644 (file)
@@ -1,12 +1,12 @@
 extern GdkPixbuf *img_pixbuf;
 extern int img_width, img_height;
 extern char img_name[];
 extern GdkPixbuf *img_pixbuf;
 extern int img_width, img_height;
 extern char img_name[];
-extern unsigned char *img_grey_buffer;
+extern unsigned short *img_grey_buffer;
 extern unsigned char *img_mark_buffer;
 extern int img_scale_x, img_scale_y;
 extern int anything_modified;
 
 extern unsigned char *img_mark_buffer;
 extern int img_scale_x, img_scale_y;
 extern int anything_modified;
 
-void create_image(const char *filename);
+void create_image(const char *filename, int resize);
 void create_or_reset_pixbuf(int resize);
 void destroy_image(void);
 void draw_image(int x, int y, int w, int h);
 void create_or_reset_pixbuf(int resize);
 void destroy_image(void);
 void draw_image(int x, int y, int w, int h);
index 2fa7e87..29135ce 100644 (file)
@@ -14,7 +14,9 @@
 static GtkWidget *level_window = NULL;
 static GtkObject *black_level_adj;
 static GtkObject *white_level_adj;
 static GtkWidget *level_window = NULL;
 static GtkObject *black_level_adj;
 static GtkObject *white_level_adj;
+static GtkWidget *scale_levels_button;
 static GtkObject *fade_level_adj;
 static GtkObject *fade_level_adj;
+static GtkWidget *yuv_mod_button;
 
 static void level_destroy(GtkWidget *widget, gpointer priv)
 {
 
 static void level_destroy(GtkWidget *widget, gpointer priv)
 {
@@ -68,7 +70,9 @@ static void apply_event(gpointer *priv)
 
        black_level = GTK_ADJUSTMENT(black_level_adj)->value / 255.0;
        white_level = GTK_ADJUSTMENT(white_level_adj)->value / 255.0;
 
        black_level = GTK_ADJUSTMENT(black_level_adj)->value / 255.0;
        white_level = GTK_ADJUSTMENT(white_level_adj)->value / 255.0;
+       scale_levels = GTK_TOGGLE_BUTTON(scale_levels_button)->active;
        fade_level = GTK_ADJUSTMENT(fade_level_adj)->value / 100.0;
        fade_level = GTK_ADJUSTMENT(fade_level_adj)->value / 100.0;
+       yuv_mod = GTK_TOGGLE_BUTTON(yuv_mod_button)->active;
        update_color(mark_selected);
        for (i = 0; i < 255; i++)
                update_color(i);
        update_color(mark_selected);
        for (i = 0; i < 255; i++)
                update_color(i);
@@ -115,7 +119,9 @@ void level_event(gpointer priv)
        GtkWidget *fade_level_label;
        GtkWidget *black_level_scroll;
        GtkWidget *white_level_scroll;
        GtkWidget *fade_level_label;
        GtkWidget *black_level_scroll;
        GtkWidget *white_level_scroll;
+       GtkWidget *scale_levels_label;
        GtkWidget *fade_level_scroll;
        GtkWidget *fade_level_scroll;
+       GtkWidget *yuv_mod_label;
        GtkWidget *button_apply;
        GtkWidget *button_reset;
        GtkWidget *box;
        GtkWidget *button_apply;
        GtkWidget *button_reset;
        GtkWidget *box;
@@ -160,12 +166,26 @@ void level_event(gpointer priv)
        white_level_scroll = gtk_hscale_new(GTK_ADJUSTMENT(white_level_adj));
        gtk_widget_show(white_level_scroll);
 
        white_level_scroll = gtk_hscale_new(GTK_ADJUSTMENT(white_level_adj));
        gtk_widget_show(white_level_scroll);
 
+       scale_levels_label = gtk_label_new("Scale levels:"); 
+       gtk_widget_show(GTK_WIDGET(scale_levels_label));
+       scale_levels_button = gtk_check_button_new();
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(scale_levels_button), scale_levels ? TRUE : FALSE);
+//     g_signal_connect(scale_levels_button, "toggled", G_CALLBACK(scale_levels_event), NULL);
+       gtk_widget_show(scale_levels_button);
+
        fade_level_label = gtk_label_new("Fade Level (%):"); 
        gtk_widget_show(GTK_WIDGET(fade_level_label));
        fade_level_adj = gtk_adjustment_new(fade_level * 100, 0, 101, 1, 1, 1);
        fade_level_scroll = gtk_hscale_new(GTK_ADJUSTMENT(fade_level_adj));
        gtk_widget_show(fade_level_scroll);
 
        fade_level_label = gtk_label_new("Fade Level (%):"); 
        gtk_widget_show(GTK_WIDGET(fade_level_label));
        fade_level_adj = gtk_adjustment_new(fade_level * 100, 0, 101, 1, 1, 1);
        fade_level_scroll = gtk_hscale_new(GTK_ADJUSTMENT(fade_level_adj));
        gtk_widget_show(fade_level_scroll);
 
+       yuv_mod_label = gtk_label_new("Use modified YUV:"); 
+       gtk_widget_show(GTK_WIDGET(yuv_mod_label));
+       yuv_mod_button = gtk_check_button_new();
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(yuv_mod_button), yuv_mod ? TRUE : FALSE);
+//     g_signal_connect(yuv_mod_button, "toggled", G_CALLBACK(yuv_mod_event), NULL);
+       gtk_widget_show(yuv_mod_button);
+
        /* buttons */
        button_reset = gtk_button_new();
        g_signal_connect(button_reset, "clicked", G_CALLBACK(reset_event), NULL);
        /* buttons */
        button_reset = gtk_button_new();
        g_signal_connect(button_reset, "clicked", G_CALLBACK(reset_event), NULL);
@@ -193,8 +213,12 @@ void level_event(gpointer priv)
        gtk_box_pack_start(GTK_BOX(vbox), black_level_scroll, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), white_level_label, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), white_level_scroll, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), black_level_scroll, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), white_level_label, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), white_level_scroll, FALSE, FALSE, 2);
+       gtk_box_pack_start(GTK_BOX(vbox), scale_levels_label, FALSE, FALSE, 2);
+       gtk_box_pack_start(GTK_BOX(vbox), scale_levels_button, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), fade_level_label, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), fade_level_scroll, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), fade_level_label, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), fade_level_scroll, FALSE, FALSE, 2);
+       gtk_box_pack_start(GTK_BOX(vbox), yuv_mod_label, FALSE, FALSE, 2);
+       gtk_box_pack_start(GTK_BOX(vbox), yuv_mod_button, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 20);
        gtk_widget_show(vbox);
 
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 20);
        gtk_widget_show(vbox);
 
index 71cff5f..c89da3c 100644 (file)
@@ -412,22 +412,23 @@ GtkWidget *colorseldlg = NULL;
 GtkColorSelection *colorsel;
 static void color_response(GtkDialog *dialog, gint response_id, gpointer user_data)
 {
 GtkColorSelection *colorsel;
 static void color_response(GtkDialog *dialog, gint response_id, gpointer user_data)
 {
-       if (response_id == GTK_RESPONSE_CANCEL) {
-               gtk_widget_destroy(colorseldlg);
-               colorseldlg = NULL;
-       }
-       if (response_id == GTK_RESPONSE_OK) {
-               GdkColor ncolor;
+       GdkColor ncolor;
 
 
+       switch (response_id) {
+       case GTK_RESPONSE_CANCEL:
+               gtk_color_selection_get_previous_color(colorsel, &ncolor);
+new_color:
                anything_modified = 1;
 
                anything_modified = 1;
 
-               gtk_color_selection_get_current_color(colorsel, &ncolor);
-               gtk_color_selection_set_previous_color(colorsel, &ncolor);
                mark_palette[mark_selected].r = ncolor.red / 256;
                mark_palette[mark_selected].g = ncolor.green / 256;
                mark_palette[mark_selected].b = ncolor.blue / 256;
                update_color(mark_selected);
                draw_image(0, 0, -1, -1);
                mark_palette[mark_selected].r = ncolor.red / 256;
                mark_palette[mark_selected].g = ncolor.green / 256;
                mark_palette[mark_selected].b = ncolor.blue / 256;
                update_color(mark_selected);
                draw_image(0, 0, -1, -1);
+               break;
+       case GTK_RESPONSE_OK:
+               gtk_color_selection_get_current_color(colorsel, &ncolor);
+               goto new_color;
        }
 }
 
        }
 }
 
@@ -473,7 +474,7 @@ static void open_event(gpointer priv)
                
                create_timeline(filename);
                if (frame_list)
                
                create_timeline(filename);
                if (frame_list)
-                       create_image(frame_list[timeline_selected].filename);
+                       create_image(frame_list[timeline_selected].filename, 1);
                free(filename);
        }
 
                free(filename);
        }
 
@@ -809,8 +810,10 @@ void palette_change(GtkTreeSelection *selection, gpointer data)
                        color.green = mark_palette[mark_selected].g * 256 + 128;
                        color.blue = mark_palette[mark_selected].b * 256 + 128;
 
                        color.green = mark_palette[mark_selected].g * 256 + 128;
                        color.blue = mark_palette[mark_selected].b * 256 + 128;
 
-                       if (colorseldlg)
+                       if (colorseldlg) {
+                               gtk_color_selection_set_previous_color (colorsel, &color);
                                gtk_color_selection_set_current_color (colorsel, &color);
                                gtk_color_selection_set_current_color (colorsel, &color);
+                       }
                }
 
                /* set current color for bightness+contrast window */
                }
 
                /* set current color for bightness+contrast window */
@@ -1206,7 +1209,7 @@ int main(int argc, char *argv[])
        if (argc > 1) {
                create_timeline(argv[1]);
                if (frame_list)
        if (argc > 1) {
                create_timeline(argv[1]);
                if (frame_list)
-                       create_image(frame_list[timeline_selected].filename);
+                       create_image(frame_list[timeline_selected].filename, 1);
        }
 
        gtk_main();
        }
 
        gtk_main();
index 5a25b86..1431182 100644 (file)
@@ -289,7 +289,7 @@ int timeline_select_and_save(int old_frame, int new_frame)
 
        timeline_selected = new_frame;
 
 
        timeline_selected = new_frame;
 
-       create_image(frame_list[new_frame].filename);
+       create_image(frame_list[new_frame].filename, 0);
 #ifdef WITH_OPENCV
        if (flowview && flow_enable && img_grey_buffer)
                create_flow_view(
 #ifdef WITH_OPENCV
        if (flowview && flow_enable && img_grey_buffer)
                create_flow_view(
index d7f14c7..af7a447 100644 (file)
@@ -185,7 +185,7 @@ again:
  */
 
 /* scale down image in img_buffer by calculating average */
  */
 
 /* scale down image in img_buffer by calculating average */
-static void scale_img(unsigned char *img_buffer, int width, int height, int scale)
+static void scale_img(unsigned short *img_buffer, int width, int height, int scale)
 {
        int w, h, i, j, x, y;
        int r, g, b;
 {
        int w, h, i, j, x, y;
        int r, g, b;
@@ -293,6 +293,7 @@ static int handle_options(int argc, char **argv)
                int option_index = 0, c;
                static struct option long_options[] = {
                        {"help", 0, 0, 'h'},
                int option_index = 0, c;
                static struct option long_options[] = {
                        {"help", 0, 0, 'h'},
+                       {"depth", 1, 0, 'd'},
                        {"in-itr-num", 1, 0, 'i'},
                        {"out-itr-num", 1, 0, 'o'},
                        {"zscale", 1, 0, 'z'},
                        {"in-itr-num", 1, 0, 'i'},
                        {"out-itr-num", 1, 0, 'o'},
                        {"zscale", 1, 0, 'z'},
@@ -303,7 +304,7 @@ static int handle_options(int argc, char **argv)
                        {0, 0, 0, 0},
                };
 
                        {0, 0, 0, 0},
                };
 
-               c = getopt_long(argc, argv, "hi:o:z:b:f:s:t:", long_options, &option_index);
+               c = getopt_long(argc, argv, "hd:i:o:z:b:f:s:t:", long_options, &option_index);
 
                if (c == -1)
                        break;
 
                if (c == -1)
                        break;
@@ -312,6 +313,10 @@ static int handle_options(int argc, char **argv)
                case 'h':
                        print_help(argv[0]);
                        exit(0);
                case 'h':
                        print_help(argv[0]);
                        exit(0);
+               case 'd':
+                       save_depth = atoi(optarg);
+                       skip_args += 2;
+                       break;
                case 'i':
                        in_itr_num = atoi(optarg);
                        skip_args += 2;
                case 'i':
                        in_itr_num = atoi(optarg);
                        skip_args += 2;
@@ -371,6 +376,7 @@ static void print_help(const char *app)
        printf("       Use list to view sequence segments between keyframes.\n");
        printf("\nOptions:\n");
        printf(" -h --help                           This help\n");
        printf("       Use list to view sequence segments between keyframes.\n");
        printf("\nOptions:\n");
        printf(" -h --help                           This help\n");
+       printf(" -d --depth <bits>                   Save images with given color bit depth (default=%d)\n", save_depth);
        printf(" -i --in-itr-num <num>               Alter inner iterations (weightening count) of colorization algorithm (default=%d)\n", in_itr_num);
        printf(" -o --out-itr-num <num>              Alter outer iterations (complete turns) of colorization algorithm (default=%d)\n", out_itr_num);
        printf(" -z --zscale <levels>                How many grids (staring with the finest) should be scaled in z direction to generate the next coarse grid ");
        printf(" -i --in-itr-num <num>               Alter inner iterations (weightening count) of colorization algorithm (default=%d)\n", in_itr_num);
        printf(" -o --out-itr-num <num>              Alter outer iterations (complete turns) of colorization algorithm (default=%d)\n", out_itr_num);
        printf(" -z --zscale <levels>                How many grids (staring with the finest) should be scaled in z direction to generate the next coarse grid ");
@@ -412,7 +418,8 @@ int main(int argc, char *argv[])
        double diff, sum;
        int dims[4];
        int w = 0, h = 0, load_w, load_h, k = 1, index = 0, z;
        double diff, sum;
        int dims[4];
        int w = 0, h = 0, load_w, load_h, k = 1, index = 0, z;
-       unsigned char *img_buffer, *img_buffer_all = NULL, *mark_buffer = NULL;
+       unsigned short *img_buffer, *img_buffer_all = NULL;
+       unsigned char *mark_buffer = NULL;
        int rc, x, y, i, ii;
        time_t start, end;
        const char* filename;
        int rc, x, y, i, ii;
        time_t start, end;
        const char* filename;
@@ -515,12 +522,12 @@ next_sequence:
 #ifdef WITH_OPENCV
                if (k > 1 && flow_enable) {
                        if (!img_buffer_all)
 #ifdef WITH_OPENCV
                if (k > 1 && flow_enable) {
                        if (!img_buffer_all)
-                               img_buffer_all = malloc(w*h*3*k);
+                               img_buffer_all = malloc(w*h*3*k*sizeof(unsigned short));
                        if (!img_buffer_all) {
                                printf("failed to create grey image array\n");
                                exit (0);
                        }
                        if (!img_buffer_all) {
                                printf("failed to create grey image array\n");
                                exit (0);
                        }
-                       memcpy(img_buffer_all + w*h*3*z, img_buffer, w*h*3);
+                       memcpy(img_buffer_all + w*h*3*z, img_buffer, w*h*3*sizeof(unsigned short));
                }
 #endif
                free(img_buffer);
                }
 #endif
                free(img_buffer);
@@ -733,13 +740,17 @@ next_sequence:
                        exit (0);
                }
                printf("Calculating optical flow for %d frames: window=%d\n", k, flow_window/scale);
                        exit (0);
                }
                printf("Calculating optical flow for %d frames: window=%d\n", k, flow_window/scale);
-       }
+       } else if (k > 1)
+               printf("Note: Optical flow is not activated!\n");
        for (z = 0; z < k-1; z++) {
                if (flow)
                        create_flow_maps(NULL, img_buffer_all + w*h*3*(z+1), img_buffer_all + w*h*3*z, w, h, flow_window/scale, 0, NULL, NULL, darrayGetPr(flow) + w*h*z, darrayGetPr(flow) + w*h*z + w*h*(k-1), NULL);
                if (flow_i)
                        create_flow_maps(img_buffer_all + w*h*3*z, NULL, img_buffer_all + w*h*3*(z+1), w, h, flow_window/scale, 0, darrayGetPr(flow_i) + w*h*z, darrayGetPr(flow_i) + w*h*z + w*h*(k-1), NULL, NULL, NULL);
        }
        for (z = 0; z < k-1; z++) {
                if (flow)
                        create_flow_maps(NULL, img_buffer_all + w*h*3*(z+1), img_buffer_all + w*h*3*z, w, h, flow_window/scale, 0, NULL, NULL, darrayGetPr(flow) + w*h*z, darrayGetPr(flow) + w*h*z + w*h*(k-1), NULL);
                if (flow_i)
                        create_flow_maps(img_buffer_all + w*h*3*z, NULL, img_buffer_all + w*h*3*(z+1), w, h, flow_window/scale, 0, darrayGetPr(flow_i) + w*h*z, darrayGetPr(flow_i) + w*h*z + w*h*(k-1), NULL, NULL, NULL);
        }
+#else
+       if (k > 1)
+               printf("Note: Optical flow is not compiled in!\n");
 #endif
        free(img_buffer_all);
        img_buffer_all = NULL;
 #endif
        free(img_buffer_all);
        img_buffer_all = NULL;
@@ -870,7 +881,7 @@ ptr2[w * h * 2 + w * y + x] = ptr[w * h * 2 + w * y + x] * 10 - 1;
        }
 
        // save result YUV array to image with RGB components
        }
 
        // save result YUV array to image with RGB components
-       img_buffer = (unsigned char *)malloc(w * h * 3);
+       img_buffer = (unsigned short *)malloc(w*h*3*sizeof(unsigned short));
        if (!img_buffer) {
                fprintf(stderr, "Failed to allocate image buffer\n");
                return 0;
        if (!img_buffer) {
                fprintf(stderr, "Failed to allocate image buffer\n");
                return 0;
index 1d0b29e..0eb60c4 100644 (file)
@@ -30,6 +30,7 @@ void save_palette(const char *filename)
        fprintf(fp, "blacklevel %f\n", black_level);
        fprintf(fp, "whitelevel %f\n", white_level);
        fprintf(fp, "fadelevel %f\n", fade_level);
        fprintf(fp, "blacklevel %f\n", black_level);
        fprintf(fp, "whitelevel %f\n", white_level);
        fprintf(fp, "fadelevel %f\n", fade_level);
+       fprintf(fp, "yuv_mod %d\n", yuv_mod);
        fclose(fp);
 }
 
        fclose(fp);
 }
 
@@ -69,10 +70,15 @@ int load_palette(const char *filename)
                        continue;
                }
                if (!strncmp(line, "fadelevel ", 10)) {
                        continue;
                }
                if (!strncmp(line, "fadelevel ", 10)) {
-                       p = line + 11;
+                       p = line + 10;
                        sscanf(p, "%lf", &fade_level);
                        continue;
                }
                        sscanf(p, "%lf", &fade_level);
                        continue;
                }
+               if (!strncmp(line, "yuv_mod ", 8)) {
+                       p = line + 8;
+                       sscanf(p, "%d", &yuv_mod);
+                       continue;
+               }
 
                /* read palette */
                if (i == 256)
 
                /* read palette */
                if (i == 256)
index 2de9f56..0ea41ef 100644 (file)
@@ -132,7 +132,7 @@ static void copy_matrix_to_map(CvMat *flow, int width, int height, double *flow_
  * flow_map_y_next = flow map for delta y of next image (result is stored here)
  *
  */
  * flow_map_y_next = flow map for delta y of next image (result is stored here)
  *
  */
-void *create_flow_maps(const unsigned char *img_prev_buffer, const unsigned char *img_next_buffer, unsigned char *img_buffer, int width, int height, int win_size, int steps, double *flow_map_x_prev, double *flow_map_y_prev, double *flow_map_x_next, double *flow_map_y_next, void *_image_preview)
+void *create_flow_maps(const unsigned short *img_prev_buffer, const unsigned short *img_next_buffer, unsigned short *img_buffer, int width, int height, int win_size, int steps, double *flow_map_x_prev, double *flow_map_y_prev, double *flow_map_x_next, double *flow_map_y_next, void *_image_preview)
 {
        IplImage *image_prev = NULL, *image = NULL, *image_next = NULL, *image_preview = _image_preview;
        CvMat *flow;
 {
        IplImage *image_prev = NULL, *image = NULL, *image_next = NULL, *image_preview = _image_preview;
        CvMat *flow;
@@ -170,7 +170,7 @@ void *create_flow_maps(const unsigned char *img_prev_buffer, const unsigned char
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
                                /* copy green channel */
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
                                /* copy green channel */
-                               CV_IMAGE_ELEM(image_prev, uchar, i, j) = img_prev_buffer[(i*width+j)*3 + 1];
+                               CV_IMAGE_ELEM(image_prev, uchar, i, j) = img_prev_buffer[(i*width+j)*3 + 1] >> 8;
                        }
                }
        }
                        }
                }
        }
@@ -178,9 +178,9 @@ void *create_flow_maps(const unsigned char *img_prev_buffer, const unsigned char
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
                                /* copy green channel */
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
                                /* copy green channel */
-                               CV_IMAGE_ELEM(image, uchar, i, j) = img_buffer[(i*width+j)*3 + 1];
+                               CV_IMAGE_ELEM(image, uchar, i, j) = img_buffer[(i*width+j)*3 + 1] >> 8;
                                if (image_preview)
                                if (image_preview)
-                                       CV_IMAGE_ELEM(image_preview, uchar, i, j) = img_buffer[(i*width+j)*3 + 1] / 2;
+                                       CV_IMAGE_ELEM(image_preview, uchar, i, j) = (img_buffer[(i*width+j)*3 + 1] / 2) >> 8;
                        }
                }
        }
                        }
                }
        }
@@ -188,7 +188,7 @@ void *create_flow_maps(const unsigned char *img_prev_buffer, const unsigned char
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
                                /* copy green channel */
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
                                /* copy green channel */
-                               CV_IMAGE_ELEM(image_next, uchar, i, j) = img_next_buffer[(i*width+j)*3 + 1];
+                               CV_IMAGE_ELEM(image_next, uchar, i, j) = img_next_buffer[(i*width+j)*3 + 1] >> 8;
                        }
                }
        }
                        }
                }
        }
@@ -236,9 +236,9 @@ void *create_flow_maps(const unsigned char *img_prev_buffer, const unsigned char
  * uv_scale = apply vector (pointing to next plane) by applying uv-color (0 to disable)
  *
  */
  * uv_scale = apply vector (pointing to next plane) by applying uv-color (0 to disable)
  *
  */
-void create_flow_view(const char *filename_prev, const char *filename_next, unsigned char *img_buffer, int width, int height, int win_size, int steps, int uv_scale)
+void create_flow_view(const char *filename_prev, const char *filename_next, unsigned short *img_buffer, int width, int height, int win_size, int steps, int uv_scale)
 {
 {
-       unsigned char *img_prev_buffer = NULL, *img_next_buffer = NULL;
+       unsigned short *img_prev_buffer = NULL, *img_next_buffer = NULL;
        double *flow_map_x_prev = NULL, *flow_map_y_prev = NULL, *flow_map_x_next = NULL, *flow_map_y_next = NULL;
        IplImage *image_preview = NULL;
        CvSize size;
        double *flow_map_x_prev = NULL, *flow_map_y_prev = NULL, *flow_map_x_next = NULL, *flow_map_y_next = NULL;
        IplImage *image_preview = NULL;
        CvSize size;
@@ -319,9 +319,9 @@ void create_flow_view(const char *filename_prev, const char *filename_next, unsi
                                                b = (double)c / 255.0;
                                        }
                                }
                                                b = (double)c / 255.0;
                                        }
                                }
-                               img_buffer[(i*width+j)*3 + 0] = r * 255.0;
-                               img_buffer[(i*width+j)*3 + 1] = g * 255.0;
-                               img_buffer[(i*width+j)*3 + 2] = b * 255.0;
+                               img_buffer[(i*width+j)*3 + 0] = r * 65535.0;
+                               img_buffer[(i*width+j)*3 + 1] = g * 65535.0;
+                               img_buffer[(i*width+j)*3 + 2] = b * 65535.0;
                        }
                }
        }
                        }
                }
        }
index 8d7cf91..a144d1f 100644 (file)
@@ -4,6 +4,6 @@ void flow_default(void);
 void save_flow(const char *filename);
 int load_flow(const char *filename);
 
 void save_flow(const char *filename);
 int load_flow(const char *filename);
 
-void *create_flow_maps(const unsigned char *img_prev_buffer, const unsigned char *img_next_buffer, unsigned char *img_buffer, int width, int height, int win_size, int steps, double *flow_map_x_prev, double *flow_map_y_prev, double *flow_map_x_next, double *flow_map_y_next, void *_image_preview);
+void *create_flow_maps(const unsigned short *img_prev_buffer, const unsigned short *img_next_buffer, unsigned short *img_buffer, int width, int height, int win_size, int steps, double *flow_map_x_prev, double *flow_map_y_prev, double *flow_map_x_next, double *flow_map_y_next, void *_image_preview);
 
 
-void create_flow_view(const char *filename_prev, const char *filename_next, unsigned char *img_buffer, int width, int height, int win_size, int steps, int uv_scale);
+void create_flow_view(const char *filename_prev, const char *filename_next, unsigned short *img_buffer, int width, int height, int win_size, int steps, int uv_scale);
index 7f324bf..f5e6fbb 100755 (executable)
--- a/src/ppm.c
+++ b/src/ppm.c
@@ -6,9 +6,11 @@
 #ifdef WITH_MAGICK
 #include <magick/api.h>
 
 #ifdef WITH_MAGICK
 #include <magick/api.h>
 
-/* load given PPM image to memory. return memory pointer, witdth and height
+int save_depth = 16;
+
+/* load given image to memory. return memory pointer, witdth and height
  * if offset is given, no memory is allocated */
  * if offset is given, no memory is allocated */
-int load_img(int offset, unsigned char **buffer, int *width, int *height,
+int load_img(int offset, unsigned short **buffer, int *width, int *height,
        const char *filename, int index)
 {
        int rc = -1;
        const char *filename, int index)
 {
        int rc = -1;
@@ -32,7 +34,7 @@ int load_img(int offset, unsigned char **buffer, int *width, int *height,
        *height = image->rows;
 
        if (offset < 0) {
        *height = image->rows;
 
        if (offset < 0) {
-               *buffer = (unsigned char *)malloc((*width) * (*height) * 3);
+               *buffer = (unsigned short *)malloc((*width) * (*height) * 3 * sizeof(unsigned short));
                if (!*buffer) {
                        printf("failed to allocate image data\n");
                        goto exit;
                if (!*buffer) {
                        printf("failed to allocate image data\n");
                        goto exit;
@@ -40,7 +42,7 @@ int load_img(int offset, unsigned char **buffer, int *width, int *height,
                offset = 0;
        }
 //     ExportImagePixels(image, 0, 0, *width, *height, "RGB", CharPixel, *buffer, NULL);
                offset = 0;
        }
 //     ExportImagePixels(image, 0, 0, *width, *height, "RGB", CharPixel, *buffer, NULL);
-       DispatchImage(image, 0, 0, *width, *height, "RGB", CharPixel, *buffer, NULL);
+       DispatchImage(image, 0, 0, *width, *height, "RGB", ShortPixel, *buffer, NULL);
 
        rc = 0;
 
 
        rc = 0;
 
@@ -58,7 +60,7 @@ exit:
 }
 
 /* save given image */
 }
 
 /* save given image */
-int save_img(unsigned char *buffer, int width, int height, const char *filename,
+int save_img(unsigned short *buffer, int width, int height, const char *filename,
        int index)
 {
        int rc = -1;
        int index)
 {
        int rc = -1;
@@ -73,11 +75,15 @@ int save_img(unsigned char *buffer, int width, int height, const char *filename,
 
        imageinfo->quality = 100;
 
 
        imageinfo->quality = 100;
 
-       image=ConstituteImage(width, height, "RGB", CharPixel, buffer, &exception);
+       image=ConstituteImage(width, height, "RGB", ShortPixel, buffer, &exception);
        if (!image) {
                printf("failed to prepare to write image\n");
                goto exit;
        }
        if (!image) {
                printf("failed to prepare to write image\n");
                goto exit;
        }
+
+       /* store as 16 bit, if lib and format supports it */
+       image->depth = save_depth;
+
        sprintf(image->filename, filename, index); /* ACHTUNG: nicht imageinfo!!! */
        if (!WriteImage(imageinfo, image)) {
                printf("failed to write image\n");
        sprintf(image->filename, filename, index); /* ACHTUNG: nicht imageinfo!!! */
        if (!WriteImage(imageinfo, image)) {
                printf("failed to write image\n");
@@ -102,7 +108,7 @@ exit:
 
 /* load given PPM image to memory. return memory pointer, witdth and height
  * if offset is given, no memory is allocated */
 
 /* load given PPM image to memory. return memory pointer, witdth and height
  * if offset is given, no memory is allocated */
-int load_img(int offset, unsigned char **buffer, int *width, int *height,
+int load_img(int offset, unsigned short **buffer, int *width, int *height,
        const char *filename, int index)
 {
        FILE *fp;
        const char *filename, int index)
 {
        FILE *fp;
@@ -164,7 +170,7 @@ again3:
                return -1;
        }
        if (offset < 0) {
                return -1;
        }
        if (offset < 0) {
-               *buffer = (unsigned char *)malloc((*width) * (*height) * 3 * words);
+               *buffer = (unsigned short *)malloc((*width) * (*height) * 3 * words * sizeof(unsigned short));
                if (!*buffer) {
                        printf("failed to allocate image data\n");
                        fclose(fp);
                if (!*buffer) {
                        printf("failed to allocate image data\n");
                        fclose(fp);
@@ -179,10 +185,18 @@ again3:
                return -1;
        }
 
                return -1;
        }
 
-       /* convert 16 to 8 bits */
-       if (words == 2) {
-               for (i = 0; i < (*width) * (*height) * 3; i++)
-                       (*buffer)[offset + i] = (*buffer)[offset + i*2];
+       /* convert 8 to 16 bits */
+       if (words == 8) {
+               for (i = (*width) * (*height) * 3 - 1; i >= 0; i--) {
+                       (*buffer)[offset + i] = ((unsigned char *)((*buffer) - offset + (i >> 1)))[0] << 8;
+                       (*buffer)[offset + i] = ((unsigned char *)((*buffer) - offset + (i >> 1)))[1] << 8;
+               }
+       } else {
+               for (i = 0; i < (*width) * (*height) * 3; i++) {
+                       /* correct bit order */
+                       (*buffer)[offset + i] = ((unsigned char *)((*buffer) - offset + i))[0] << 8;
+                       (*buffer)[offset + i] |= ((unsigned char *)((*buffer) - offset + i))[1];
+               }
        }
 
        fclose(fp);
        }
 
        fclose(fp);
@@ -191,7 +205,7 @@ again3:
 }
 
 /* save given image */
 }
 
 /* save given image */
-int save_img(unsigned char *buffer, int width, int height, const char *filename,
+int save_img(unsigned short *buffer, int width, int height, const char *filename,
        int index)
 {
        FILE *fp;
        int index)
 {
        FILE *fp;
@@ -205,8 +219,13 @@ int save_img(unsigned char *buffer, int width, int height, const char *filename,
                printf("failed to write image\n");
                return -1;
        }
                printf("failed to write image\n");
                return -1;
        }
-       fprintf(fp, "P6\n%d %d\n255\n", width, height);
-       rc = fwrite(buffer, width * height * 3, 1, fp);
+       fprintf(fp, "P6\n%d %d\n65535\n", width, height);
+       for (i = 0; i < (*width) * (*height) * 3; i++) {
+               /* correct bit order */
+               rc = fputc(((unsigned char *)((*buffer) - offset + i))[0] >> 8, fp);
+               rc = fputc(((unsigned char *)((*buffer) - offset + i))[1], fp);
+       }
+
        fclose(fp);
 
        return rc;
        fclose(fp);
 
        return rc;
@@ -216,7 +235,7 @@ int save_img(unsigned char *buffer, int width, int height, const char *filename,
 /* convert an image to a three dimensional array of double
  * the size is: width, height, 3
  */
 /* convert an image to a three dimensional array of double
  * the size is: width, height, 3
  */
-void img2array(unsigned char *img, int iw, int ih, double *array, int aw,
+void img2array(unsigned short *img, int iw, int ih, double *array, int aw,
        int ah)
 {
        int x, y;
        int ah)
 {
        int x, y;
@@ -225,9 +244,9 @@ void img2array(unsigned char *img, int iw, int ih, double *array, int aw,
 
        for (y = 0; y < ih; y++) {
                for (x = 0; x < iw; x++) {
 
        for (y = 0; y < ih; y++) {
                for (x = 0; x < iw; x++) {
-                       r = img[(x+iw*y)*3] / 255.0F;
-                       g = img[(x+iw*y)*3+1] / 255.0F;
-                       b = img[(x+iw*y)*3+2] / 255.0F;
+                       r = img[(x+iw*y)*3] / 65535.0F;
+                       g = img[(x+iw*y)*3+1] / 65535.0F;
+                       b = img[(x+iw*y)*3+2] / 65535.0F;
                        array[x+aw*y] = r;
                        array[x+aw*y+plane] = g;
                        array[x+aw*y+plane+plane] = b;
                        array[x+aw*y] = r;
                        array[x+aw*y+plane] = g;
                        array[x+aw*y+plane+plane] = b;
@@ -238,7 +257,7 @@ void img2array(unsigned char *img, int iw, int ih, double *array, int aw,
 /* convert a three dimensional array of double to an image
  * the size is: width, height, 3
  */
 /* convert a three dimensional array of double to an image
  * the size is: width, height, 3
  */
-void array2img(double *array, int aw, int ah, unsigned char *img, int iw,
+void array2img(double *array, int aw, int ah, unsigned short *img, int iw,
        int ih)
 {
        int x, y, c;
        int ih)
 {
        int x, y, c;
@@ -250,23 +269,23 @@ void array2img(double *array, int aw, int ah, unsigned char *img, int iw,
                        r = array[x+aw*y];
                        g = array[x+aw*y+plane];
                        b = array[x+aw*y+plane+plane];
                        r = array[x+aw*y];
                        g = array[x+aw*y+plane];
                        b = array[x+aw*y+plane+plane];
-                       c = (r * 255.0F + 0.5F);
+                       c = (r * 65535.0F + 0.5F);
                        if (c < 0)
                                c = 0;
                        if (c < 0)
                                c = 0;
-                       else if (c > 255)
-                               c = 255;
+                       else if (c > 65535)
+                               c = 65535;
                        img[(x+iw*y)*3] = c;
                        img[(x+iw*y)*3] = c;
-                       c = (g * 255.0F + 0.5F);
+                       c = (g * 65535.0F + 0.5F);
                        if (c < 0)
                                c = 0;
                        if (c < 0)
                                c = 0;
-                       else if (c > 255)
-                               c = 255;
+                       else if (c > 65535)
+                               c = 65535;
                        img[(x+iw*y)*3+1] = c;
                        img[(x+iw*y)*3+1] = c;
-                       c = (b * 255.0F + 0.5F);
+                       c = (b * 65535.0F + 0.5F);
                        if (c < 0)
                                c = 0;
                        if (c < 0)
                                c = 0;
-                       else if (c > 255)
-                               c = 255;
+                       else if (c > 65535)
+                               c = 65535;
                        img[(x+iw*y)*3+2] = c;
                }
        }
                        img[(x+iw*y)*3+2] = c;
                }
        }
index 344bb39..968b70c 100644 (file)
--- a/src/ppm.h
+++ b/src/ppm.h
@@ -1,5 +1,6 @@
-int load_img(int offset, unsigned char **buffer, int *width, int *height, const char *filename, int index);
-int save_img(unsigned char *buffer, int width, int height, const char *filename, int index);
-void img2array(unsigned char *img, int iw, int ih, double *array, int aw, int ah);
-void array2img(double *array, int aw, int ah, unsigned char *img, int iw, int ih);
+extern int save_depth;
+int load_img(int offset, unsigned short **buffer, int *width, int *height, const char *filename, int index);
+int save_img(unsigned short *buffer, int width, int height, const char *filename, int index);
+void img2array(unsigned short *img, int iw, int ih, double *array, int aw, int ah);
+void array2img(double *array, int aw, int ah, unsigned short *img, int iw, int ih);
 
 
index ecaa195..ec22fde 100644 (file)
--- a/src/yuv.c
+++ b/src/yuv.c
@@ -6,10 +6,65 @@
 #include "yuv.h"
 double black_level = 0.00;
 double white_level = 1.00;
 #include "yuv.h"
 double black_level = 0.00;
 double white_level = 1.00;
+int scale_levels = 0; /* scale between black and white level */
 double fade_level = 0.20;
 double fade_level = 0.20;
+int yuv_mod = 0; /* UV vectors are not affected by lightness of the pixle */
+
+/* Modified YUV:
+ *
+ * Instead of having U and V vector length affected by the lightnes of the
+ * pixle, we only apply the saturation to U and V. This prevents change of
+ * saturation when convertig YUV /with different Y) back to RGB.
+ */
+
+inline double max_rgb(double r, double g, double b)
+{
+       if (r > g) {
+               if (r > b)
+                       return r;
+               else if (b > g)
+                       return b;
+               return g;
+       }
+       if (b > g)
+               return b;
+       return g;
+}
+
+/* modified YUV space */
+inline void rgb2yuv_pixle_mod(double r, double g, double b, double *y, double *u, double *v)
+{
+       double max = 0;
+       double r_, g_, b_, y_;
+
+       /* 1. scale RGB to maximum lightness */
+       /* 1.1 find maximum value */
+       max = max_rgb(r, g, b);
+       /* 1.2 if value is too low, assume grey pixle */
+       if (max < 0.001) {
+               *y = *u = *v = 0;
+               return;
+       }
+       /* 1.3 use max to scale RGB to max lightness */
+       r_ = r / max;
+       g_ = g / max;
+       b_ = b / max;
+
+       /* 2. convert to modified YUV */
+       /* 2.1 use Y from original RGB */
+       *y = 0.299*r + 0.587*g + 0.114*b;
+       /* 2.2 use UV from scaled RGB */
+       y_ = 0.299*r_ + 0.587*g_ + 0.114*b_;
+       *u = 0.492*(b_ - y_);
+       *v = 0.877*(r_ - y_);
+}
 
 void rgb2yuv_pixle(double r, double g, double b, double *y, double *u, double *v)
 {
 
 void rgb2yuv_pixle(double r, double g, double b, double *y, double *u, double *v)
 {
+       if (yuv_mod) {
+               rgb2yuv_pixle_mod(r, g, b, y, u, v);
+               return;
+       }
        *y = 0.299*r + 0.587*g + 0.114*b;
        *u = 0.492*(b - *y);
        *v = 0.877*(r - *y);
        *y = 0.299*r + 0.587*g + 0.114*b;
        *u = 0.492*(b - *y);
        *v = 0.877*(r - *y);
@@ -34,47 +89,123 @@ void rgb2yuv(double *src, double *dst, int width, int height)
        }
 }
 
        }
 }
 
-//#define SCALE_LEVEL
-void yuv2rgb_pixle(double y, double u, double v, double *r, double *g, double *b)
+inline int _scale_levels(double *y, double *r, double *g, double *b)
 {
 {
-       double nu, nv, uv, nuv, ny;
-       double fade;
+       double ny;
 
        /* prevent from crashing/artefacts, if black level is at full level */
        if (black_level > 0.999) {
                *r = *g = *b = 1.0;
 
        /* prevent from crashing/artefacts, if black level is at full level */
        if (black_level > 0.999) {
                *r = *g = *b = 1.0;
-               return;
+               return -1;
        }
        if (white_level < 0.001) {
                *r = *g = *b = 0.0;
        }
        if (white_level < 0.001) {
                *r = *g = *b = 0.0;
-               return;
+               return -1 ;
        }
        if (white_level - black_level < 0.001) {
                *r = *b = 1.0 ; *g = 0.0;
        }
        if (white_level - black_level < 0.001) {
                *r = *b = 1.0 ; *g = 0.0;
-               return;
+               return -1;
        }
        /* scale down, black level becomes 0 */
        if (black_level > 0.0 || white_level < 1.0) {
        }
        /* scale down, black level becomes 0 */
        if (black_level > 0.0 || white_level < 1.0) {
-               ny = (y - black_level) / (white_level - black_level);
+               ny = (*y - black_level) / (white_level - black_level);
                if (ny < 0.0) {
                if (ny < 0.0) {
-#ifndef SCALE_LEVEL
-                       *r = *g = *b = y;
-#else
-                       *r = *g = *b = 0.0;
-#endif
-                       return;
+                       if (scale_levels)
+                               *r = *g = *b = 0.0;
+                       else
+                               *r = *g = *b = *y;
+                       return -1;
                }
                if (ny > 1.0) {
                }
                if (ny > 1.0) {
-#ifndef SCALE_LEVEL
-                       *r = *g = *b = y;
-#else
-                       *r = *g = *b = 1.0;
-#endif
-                       return;
+                       if (scale_levels)
+                               *r = *g = *b = 1.0;
+                       else
+                               *r = *g = *b = *y;
+                       return -1;
                }
                }
-               y = ny;
+               *y = ny;
        }
 
        }
 
+       return 0;
+}
+
+inline void _unscale_levels(double *r, double *g, double *b)
+{
+       if (scale_levels)
+               return;
+       /* scale up, so 0 becomes black level */
+       if (black_level > 0.0 || white_level < 1.0) {
+               *r = black_level + *r * (white_level - black_level);
+               *g = black_level + *g * (white_level - black_level);
+               *b = black_level + *b * (white_level - black_level);
+       }
+}
+
+/* modified YUV space */
+void yuv2rgb_pixle_mod(double y, double u, double v, double *r, double *g, double *b)
+{
+       double r_, g_, b_, y_;
+       double max, scale;
+       double is_dist, must_dist;
+
+       if (_scale_levels(&y, r, g, b))
+               return;
+
+       /* 1. get RGB from U and V with maximum lightness */
+       /* 1.1 U and V conversion without Y */
+       r_ = v/0.877;
+       g_ = -0.395*u - 0.581*v;
+       b_ = u/0.492;
+       /* 1.2 find maximum value */
+       max = max_rgb(r_, g_, b_);
+       /* 1.3 maximize RGB */
+       r_ = 1.0-max+r_;
+       g_ = 1.0-max+g_;
+       b_ = 1.0-max+b_;
+
+       /* 2. calculate scale factor to scale RGB (with max lightness) to target Y */
+       /* 2.1 calculate Y of scaled RGB */
+       y_ = 0.299*r_ + 0.587*g_ + 0.114*b_;
+       /* 2.2 calculate scale factor */
+       scale = y/y_;
+
+       /* 3. scale RGB (with max lightness) to target Y and clip (by reducing saturation), if needed */
+       /* 3.1 scale RGB with factor */
+       r_ *= scale;
+       g_ *= scale;
+       b_ *= scale;
+       /* 3.2 finx max value to clip if needed */
+       max = max_rgb(r_, g_, b_);
+       /* 3.3 clip by reducing saturation */
+       if (max > 1.0) {
+               is_dist = max-y;
+               must_dist = 1-y;
+               *r = (r_-y)/is_dist*must_dist + y;
+               *g = (g_-y)/is_dist*must_dist + y;
+               *b = (b_-y)/is_dist*must_dist + y;
+       } else {
+               *r = r_;
+               *g = g_;
+               *b = b_;
+       }
+
+       _unscale_levels(r, g, b);
+}
+
+//#define SCALE_LEVEL
+void yuv2rgb_pixle(double y, double u, double v, double *r, double *g, double *b)
+{
+       double nu, nv, uv, nuv;
+       double fade;
+
+       if (yuv_mod) {
+               yuv2rgb_pixle_mod(y, u, v, r, g, b);
+               return;
+       }
+
+       if (_scale_levels(&y, r, g, b))
+               return;
+
        /* scale UV vector lengh between black level and fade level */
        if (y < fade_level && fade_level > 0.001) {
                fade = y / fade_level;
        /* scale UV vector lengh between black level and fade level */
        if (y < fade_level && fade_level > 0.001) {
                fade = y / fade_level;
@@ -141,14 +272,7 @@ void yuv2rgb_pixle(double y, double u, double v, double *r, double *g, double *b
                *b = y + u/0.492;
        }
 
                *b = y + u/0.492;
        }
 
-#ifndef SCALE_LEVEL
-       /* scale up, so 0 becomes black level */
-       if (black_level > 0.0 || white_level < 1.0) {
-               *r = black_level + *r * (white_level - black_level);
-               *g = black_level + *g * (white_level - black_level);
-               *b = black_level + *b * (white_level - black_level);
-       }
-#endif
+       _unscale_levels(r, g, b);
 }
 
 void yuv2rgb(double *src, double *dst, int width, int height)
 }
 
 void yuv2rgb(double *src, double *dst, int width, int height)
index 3f5153e..307e7f0 100644 (file)
--- a/src/yuv.h
+++ b/src/yuv.h
@@ -6,4 +6,6 @@ void yuv2rgb(double *src, double *dst, int width, int height);
 
 extern double black_level;
 extern double white_level;
 
 extern double black_level;
 extern double white_level;
+extern int scale_levels;
 extern double fade_level;
 extern double fade_level;
+extern int yuv_mod;
index 1b4739f..ca49e65 100644 (file)
@@ -5,30 +5,30 @@
 #include "../src/ppm.h"
 
 /* split interlaced image into two fields */
 #include "../src/ppm.h"
 
 /* split interlaced image into two fields */
-static void split_image(const unsigned char *source, unsigned char *dest1,
-       unsigned char *dest2, int width, int height)
+static void split_image(const unsigned short *source, unsigned short *dest1,
+       unsigned short *dest2, int width, int height)
 {
        int y;
 
        for (y = 0; y < (height / 2); y++) {
 {
        int y;
 
        for (y = 0; y < (height / 2); y++) {
-               memcpy(dest2 + width * y * 3,
-                       source + width * y * 6, width * 3);
-               memcpy(dest1 + width * y * 3,
-                       source + width * y * 6 + width * 3, width * 3);
+               memcpy(dest2 + width * y * 3, source + width * y * 6,
+                       width * 3 * sizeof(unsigned short));
+               memcpy(dest1 + width * y * 3, source + width * y * 6 + width * 3,
+                       width * 3 * sizeof(unsigned short));
        }
 }
 
 /* joint two fields into interlaced image */
        }
 }
 
 /* joint two fields into interlaced image */
-static void join_image(const unsigned char *source1, unsigned char *source2,
-       unsigned char *dest, int width, int height)
+static void join_image(const unsigned short *source1, unsigned short *source2,
+       unsigned short *dest, int width, int height)
 {
        int y;
 
        for (y = 0; y < (height / 2); y++) {
 {
        int y;
 
        for (y = 0; y < (height / 2); y++) {
-               memcpy(dest + width * y * 6,
-                       source2 + width * y * 3, width * 3);
-               memcpy(dest + width * y * 6 + width * 3,
-                       source1 + width * y * 3, width * 3);
+               memcpy(dest + width * y * 6, source2 + width * y * 3,
+                       width * 3 * sizeof(unsigned short));
+               memcpy(dest + width * y * 6 + width * 3, source1 + width * y * 3,
+                       width * 3 * sizeof(unsigned short));
        }
 }
 
        }
 }
 
@@ -38,41 +38,50 @@ int mode;
 
 int main(int argc, char *argv[])
 {
 
 int main(int argc, char *argv[])
 {
-       unsigned char *field1_img = NULL, *field2_img = NULL, *frame_img = NULL;
+       unsigned short *field1_img = NULL, *field2_img = NULL, *frame_img = NULL;
        int width, height;
        int frame, field;
        int width, height;
        int frame, field;
+       int _argc = argc - 1;
+       int _arg = 1;
 
 
-       if (argc <= 4) {
+       if (_argc > 1 && !strcmp(argv[_arg], "--depth")) {
+               save_depth = atoi(argv[_arg+1]);
+               _arg += 2;
+               _argc -= 2;
+       }
+
+       if (_argc != 4) {
 usage:
                printf("This tool will split images to fields or join from frames.\n");
                printf("The odd lines (second line, fourth line, ...) is the first field.\n\n");
 usage:
                printf("This tool will split images to fields or join from frames.\n");
                printf("The odd lines (second line, fourth line, ...) is the first field.\n\n");
-               printf("Usage: %s frame2field <field> <frame> <first>\n", argv[0]);
-               printf("       %s field2frame <frame> <field> <first>\n", argv[0]);
+               printf("Usage: %s [--depth 8] frame2field <field> <frame> <first>\n", argv[0]);
+               printf("       %s [--depth 8] field2frame <frame> <field> <first>\n", argv[0]);
+               printf(" --depth <bits>   Change color depth from default %d to given bits\n", save_depth);
                return 0;
        }
 
                return 0;
        }
 
-       if (!strcmp(argv[1], "frame2field"))
+       if (!strcmp(argv[_arg], "frame2field"))
                mode = MODE_FRAME_2_FIELD;
                mode = MODE_FRAME_2_FIELD;
-       else if (!strcmp(argv[1], "field2frame"))
+       else if (!strcmp(argv[_arg], "field2frame"))
                mode = MODE_FIELD_2_FRAME;
        else
                goto usage;
 
                mode = MODE_FIELD_2_FRAME;
        else
                goto usage;
 
-       frame = field = atoi(argv[4]);
+       frame = field = atoi(argv[_arg+2]);
 
 next_frame:
        printf("\n\nProcessing frame %d, field %d+%d\n", frame, field, field+1);
        if (mode == MODE_FRAME_2_FIELD) {
 
 next_frame:
        printf("\n\nProcessing frame %d, field %d+%d\n", frame, field, field+1);
        if (mode == MODE_FRAME_2_FIELD) {
-               if (load_img(-1, &frame_img, &width, &height, argv[2], frame++))
+               if (load_img(-1, &frame_img, &width, &height, argv[_arg+1], frame++))
                        goto out;
                        goto out;
-               if (!(field1_img = malloc(width * height/2 * 3)))
+               if (!(field1_img = malloc(width * height/2 * 3 * sizeof(unsigned short))))
                        goto out;
                        goto out;
-               if (!(field2_img = malloc(width * height/2 * 3)))
+               if (!(field2_img = malloc(width * height/2 * 3 * sizeof(unsigned short))))
                        goto out;
                split_image(frame_img, field1_img, field2_img, width, height);
                        goto out;
                split_image(frame_img, field1_img, field2_img, width, height);
-               if (save_img(field1_img, width, height/2, argv[3], field++))
+               if (save_img(field1_img, width, height/2, argv[_arg+2], field++))
                        goto out;
                        goto out;
-               if (save_img(field2_img, width, height/2, argv[3], field++))
+               if (save_img(field2_img, width, height/2, argv[_arg+2], field++))
                        goto out;
                free(frame_img);
                free(field1_img);
                        goto out;
                free(frame_img);
                free(field1_img);
@@ -80,14 +89,14 @@ next_frame:
                goto next_frame;
        }
        if (mode == MODE_FIELD_2_FRAME) {
                goto next_frame;
        }
        if (mode == MODE_FIELD_2_FRAME) {
-               if (load_img(-1, &field1_img, &width, &height, argv[2], field++))
+               if (load_img(-1, &field1_img, &width, &height, argv[_arg+1], field++))
                        goto out;
                        goto out;
-               if (load_img(-1, &field2_img, &width, &height, argv[2], field++))
+               if (load_img(-1, &field2_img, &width, &height, argv[_arg+1], field++))
                        goto out;
                        goto out;
-               if (!(frame_img = malloc(width * height*2 * 3)))
+               if (!(frame_img = malloc(width * height*2 * 3 * sizeof(unsigned short))))
                        goto out;
                join_image(field1_img, field2_img, frame_img, width, height*2);
                        goto out;
                join_image(field1_img, field2_img, frame_img, width, height*2);
-               if (save_img(frame_img, width, height*2, argv[3], frame++))
+               if (save_img(frame_img, width, height*2, argv[_arg+2], frame++))
                        goto out;
                free(field1_img);
                free(field2_img);
                        goto out;
                free(field1_img);
                free(field2_img);
index e3c63c6..5a2d718 100644 (file)
--- a/version.h
+++ b/version.h
@@ -1 +1 @@
-"0.2"
+"0.3"