Refactor processing of image, Add alpha channel
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 26 Apr 2015 06:06:11 +0000 (08:06 +0200)
committerroot <root@dion.jolly.ten>
Thu, 14 May 2015 19:09:25 +0000 (21:09 +0200)
Command line tool and GUI use the same code base to prepare and
postpare before and after colorization.

During this refactoring, alpha channel support (change transparency)
was added.

Yes, I know that two features in one commit are bad, but the refactoring
was required to make things easier while implementing alpha support.

22 files changed:
gui/Makefile.am
gui/brightcontrast.c
gui/colorize.c
gui/image.c
gui/palette.c
lib/colorize.c
lib/colorize.h
lib/darray.c
src/Makefile.am
src/colorize.c
src/img.c [new file with mode: 0755]
src/img.h [new file with mode: 0644]
src/mark.c
src/mark.h
src/opticalflow.c
src/opticalflow.h
src/ppm.c [deleted file]
src/ppm.h [deleted file]
src/process.c [new file with mode: 0644]
src/process.h [new file with mode: 0644]
tools/Makefile.am
tools/fields.c

index df2e182..737b0d2 100644 (file)
@@ -18,9 +18,10 @@ bin_PROGRAMS = \
        colorize_gtk
 
 colorize_gtk_SOURCES = \
-       ../src/ppm.c \
+       ../src/img.c \
        ../src/yuv.c \
        ../src/mark.c \
+       ../src/process.c \
        image.c \
        palette.c \
        timeline.c \
index b6bddbc..1f9e159 100644 (file)
@@ -15,6 +15,7 @@
 static GtkWidget *bc_window = NULL;
 static GtkObject *bright_adj;
 static GtkObject *contrast_adj;
+static GtkObject *alpha_adj;
 
 static void bc_destroy(GtkWidget *widget, gpointer priv)
 {
@@ -50,11 +51,12 @@ static void reset_event(gpointer *priv)
 
        mark_palette[mark_selected].bright = 0;
        mark_palette[mark_selected].contrast = 1;
+       mark_palette[mark_selected].alpha = 1;
        gtk_adjustment_set_value(GTK_ADJUSTMENT(bright_adj), mark_palette[mark_selected].bright * 100);
        gtk_adjustment_set_value(GTK_ADJUSTMENT(contrast_adj), mark_palette[mark_selected].contrast * 100);
+       gtk_adjustment_set_value(GTK_ADJUSTMENT(alpha_adj), mark_palette[mark_selected].alpha * 100);
        update_color(mark_selected);
-       if (preview)
-               draw_image(0, 0, -1, -1);
+       draw_image(0, 0, -1, -1); /* alpha may change, so always update */
 }
 
 static void apply_event(gpointer *priv)
@@ -63,9 +65,9 @@ static void apply_event(gpointer *priv)
 
        mark_palette[mark_selected].bright = GTK_ADJUSTMENT(bright_adj)->value / 100.0;
        mark_palette[mark_selected].contrast = GTK_ADJUSTMENT(contrast_adj)->value / 100.0;
+       mark_palette[mark_selected].alpha = GTK_ADJUSTMENT(alpha_adj)->value / 100.0;
        update_color(mark_selected);
-       if (preview)
-               draw_image(0, 0, -1, -1);
+       draw_image(0, 0, -1, -1); /* alpha may change, so always update */
 }
 
 static GtkWidget *xpm_label_box( const gchar *stock_id,
@@ -106,6 +108,8 @@ void bc_event(gpointer priv)
        GtkWidget *bright_scroll;
        GtkWidget *contrast_label;
        GtkWidget *contrast_scroll;
+       GtkWidget *alpha_label;
+       GtkWidget *alpha_scroll;
        GtkWidget *button_apply;
        GtkWidget *button_reset;
        GtkWidget *box;
@@ -148,6 +152,11 @@ void bc_event(gpointer priv)
        contrast_adj = gtk_adjustment_new(mark_palette[mark_selected].contrast * 100, -500, 501, 1, 1, 1);
        contrast_scroll = gtk_hscale_new(GTK_ADJUSTMENT(contrast_adj));
        gtk_widget_show(contrast_scroll);
+       alpha_label = gtk_label_new("Alpha:"); 
+       gtk_widget_show(GTK_WIDGET(alpha_label));
+       alpha_adj = gtk_adjustment_new(mark_palette[mark_selected].alpha * 100, 0, 101, 1, 1, 1);
+       alpha_scroll = gtk_hscale_new(GTK_ADJUSTMENT(alpha_adj));
+       gtk_widget_show(alpha_scroll);
 
        /* buttons */
        button_reset = gtk_button_new();
@@ -176,6 +185,8 @@ void bc_event(gpointer priv)
        gtk_box_pack_start(GTK_BOX(vbox), bright_scroll, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), contrast_label, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), contrast_scroll, FALSE, FALSE, 2);
+       gtk_box_pack_start(GTK_BOX(vbox), alpha_label, FALSE, FALSE, 2);
+       gtk_box_pack_start(GTK_BOX(vbox), alpha_scroll, FALSE, FALSE, 2);
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 20);
        gtk_widget_show(vbox);
 
@@ -190,6 +201,7 @@ void bc_set_current(void)
 
        gtk_adjustment_set_value(GTK_ADJUSTMENT(bright_adj), mark_palette[mark_selected].bright * 100);
        gtk_adjustment_set_value(GTK_ADJUSTMENT(contrast_adj), mark_palette[mark_selected].contrast * 100);
+       gtk_adjustment_set_value(GTK_ADJUSTMENT(alpha_adj), mark_palette[mark_selected].alpha * 100);
 }
 
 
index 61e6345..8a321b0 100644 (file)
@@ -8,22 +8,22 @@
 #include "image.h"
 #include "colorize.h"
 #include "../src/mark.h"
-#include "../src/ppm.h"
+#include "../src/img.h"
 #include "../src/yuv.h"
 #include "../src/dir_seperator.h"
 #include "../lib/darray.h"
 #include "../lib/colorize.h"
+#include "../src/process.h"
 #include "palette.h"
 #include "timeline.h"
 
-#define min(x,y) ((x < y) ? x : y)
-
 struct colorize_priv {
        GtkWidget *window;
        GdkPixbuf *pixbuf;
-       int width, height;
+       int width, height, alpha;
        char filename[256];
        char folder[256];
+       unsigned short *img;
 };
 
 static void colorize_destroy(GtkWidget *widget, gpointer priv)
@@ -32,6 +32,7 @@ static void colorize_destroy(GtkWidget *widget, gpointer priv)
 
        gtk_widget_destroy(cp->window);
        g_object_unref(cp->pixbuf);
+       free(cp->img);
        free(cp);
 }
 
@@ -54,9 +55,6 @@ static gboolean colorize_key_press(GtkWidget *widget, GdkEventKey *event, gpoint
 static void save_event(gpointer *priv)
 {
        struct colorize_priv *cp = (struct colorize_priv *) priv;
-       guchar *data;
-       int rs, i, j;
-       unsigned short *buffer;
        GtkWidget *dialog;
        char *filename = NULL;
 
@@ -78,19 +76,8 @@ static void save_event(gpointer *priv)
        if (!filename)
                return;
 
-       data = gdk_pixbuf_get_pixels(cp->pixbuf);
-        rs = gdk_pixbuf_get_rowstride(cp->pixbuf);
-       buffer = malloc(cp->width*cp->height*3*sizeof(unsigned short));
-
-       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] << 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;
-               }
-       }
-
-       save_img(buffer, cp->width, cp->height, filename, 0);
+       printf("alpha=%d\n", cp->alpha);
+       save_img(cp->img, cp->width, cp->height, cp->alpha, filename, 0);
 }
 
 static void dummy_event(gpointer *priv)
@@ -106,11 +93,12 @@ static void close_event(gpointer *priv)
 
 void colorize_image(void)
 {
-       darray_t *gI = NULL, *cI = NULL, *markIm = NULL, *ntscIm = NULL;
-       double *ptr, *ptr2, *ptr3;
+       darray_t *gI = NULL, *cI = NULL, *I = NULL, *mI = NULL;
+       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;
        int dims[4];
        int width = img_width, height = img_height;
-       int features, change_bc;
+       int features, change_bc, change_alpha;
+       char *feat_names[20];
        int i, j;
        int c;
        int rc;
@@ -138,8 +126,8 @@ void colorize_image(void)
                printerror("No memory: failed to create grey image array");
                goto error;
        }
-       ptr = darrayGetPr(gI);
-       img2array(img_grey_buffer, img_width, img_height, ptr, width, height);
+       ptr_gI = darrayGetPr(gI);
+       img2array_short(img_grey_buffer, width, height, ptr_gI, width, height);
 
        /* generade marked color image */
        dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
@@ -148,98 +136,51 @@ void colorize_image(void)
                printerror("No memory: failed to create marked image array");
                goto error;
        }
-       ptr = darrayGetPr(cI);
-       img2array(img_grey_buffer, img_width, img_height, ptr, width, height);
-       change_bc = 0;
-       for (i = 0; i < img_height; i++) {
-               for (j = 0; j < img_width; j++) {
+       ptr_cI = darrayGetPr(cI);
+       img2array_short(img_grey_buffer, width, height, ptr_cI, width, height);
+       change_bc = change_alpha = 0;
+       for (i = 0; i < height; i++) {
+               for (j = 0; j < width; j++) {
                        /* do not apply mask on index 0 */
-                       c = img_mark_buffer[i*img_width+j];
+                       c = img_mark_buffer[i*width+j];
                        if (c == 0)
                                continue;
                        /* check for any brightness/contrast change */
                        if (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1)
                                change_bc = 1;
+                       /* check for any alpha change */
+                       if (mark_palette[c-1].alpha < 1)
+                               change_alpha = 1;
                        /* do not apply white pixles, this meas: keep original color */
                        if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
                                continue;
-                       ptr[i*width+j] = mark_palette[c-1].r / 255.0F;
-                       ptr[i*width+j + width*height] = mark_palette[c-1].g / 255.0F;
-                       ptr[i*width+j + width*height*2] = mark_palette[c-1].b / 255.0F;
+                       ptr_cI[i*width+j] = mark_palette[c-1].r / 255.0F;
+                       ptr_cI[i*width+j + width*height] = mark_palette[c-1].g / 255.0F;
+                       ptr_cI[i*width+j + width*height*2] = mark_palette[c-1].b / 255.0F;
                }
        }
 
-       // convert grey image into YUV
-       ptr = darrayGetPr(gI);
-       rgb2yuv(ptr, ptr, width, height);
+       rc = alloc_I_arrays(&I, &mI, width, height, 1, &features, feat_names, change_alpha, change_bc);
+       if (rc)
+               goto error;
 
-       // convert marked image into YUV
-       ptr = darrayGetPr(cI);
-       rgb2yuv(ptr, ptr, width, height);
+       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);
 
-       /* create color mask and ntsc arrays for the colorization process */
-       dims[0] = width; dims[1] = height; dims[2] = 1;
-       markIm = darrayCreate(3, dims);
-       if (!markIm) {
-               printerror("No memory: failed to create color array");
-               goto error;
-       }
-       features = (change_bc) ? 4 : 2;
-       dims[0] = width; dims[1] = height; dims[2] = features+1; dims[3] = 1;
-       ntscIm = darrayCreate(4, dims);
-       if (!ntscIm) {
-               printerror("No memory: failed to create ntsc array");
-               goto error;
-       }
+       // convert original image into YUV
+       rgb2yuv(ptr_gI, ptr_gI, width, height);
+       // convert maked image into YUV
+       rgb2yuv(ptr_cI, ptr_cI, width, height);
 
-       /* apply mask to markIm */
-       ptr = darrayGetPr(markIm);
-       for (i = 0; i < img_height; i++) {
-               for (j = 0; j < img_width; j++) {
+       /* apply mask to mI */
+       for (i = 0; i < height; i++) {
+               for (j = 0; j < width; j++) {
                        /* do not apply mask on index 0 */
-                       c = img_mark_buffer[i*img_width+j];
-                       ptr[i*width+j] = (c == 0) ? 0.0F : 1.0F;
+                       c = img_mark_buffer[i*width+j];
+                       ptr_m[i*width+j] = (c == 0) ? 0.0F : 1.0F;
                }
        }
 
-       // generate NTSC image: use luminance from original image and chrominance from original or marked image
-       ptr = darrayGetPr(gI);
-       ptr2 = darrayGetPr(cI);
-       ptr3 = darrayGetPr(ntscIm);
-       memcpy(ptr3, ptr, width * height * sizeof(double));
-       for (i = 0; i < img_height; i++) {
-               for (j = 0; j < img_width; j++) {
-                       c = img_mark_buffer[i*img_width+j];
-                       if (c == 0) {
-                               ptr3[width * height + width * i + j] = ptr[width * height + width * i + j];
-                               ptr3[width * height * 2 + width * i + j] = ptr[width * height * 2 + width * i + j];
-                       } else {
-                               ptr3[width * height + width * i + j] = ptr2[width * height + width * i + j];
-                               ptr3[width * height * 2 + width * i + j] = ptr2[width * height * 2 + width * i + j];
-                       }
-               }
-       }
-       /* if we have a change, we modify brightness+contrast first */
-       if (change_bc) {
-               /* apply brightness and contrast from makred pixles to grey image */
-               for (i = 0; i < height; i++) {
-                       for (j = 0; j < width; j++) {
-                               ptr3[i*width+j] = ptr[i*width+j];
-                               if (j < img_width && i < img_height) {
-                                       /* use unchanged brightness and contrast on index 0 */
-                                       c = img_mark_buffer[i*img_width+j];
-                               } else
-                                       c = 0;
-                               if (c == 0) {
-                                       ptr3[i*width+j + width*height*3] = 0;
-                                       ptr3[i*width+j + width*height*4] = 0.1;
-                               } else {
-                                       ptr3[i*width+j + width*height*3] = mark_palette[c-1].bright / 10.0;
-                                       ptr3[i*width+j + width*height*4] = mark_palette[c-1].contrast / 10.0;
-                               }
-                       }
-               }
-       }
+       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);
 
        /* destroy temporary gI and cI */
        darrayDestroy(gI);
@@ -248,56 +189,66 @@ void colorize_image(void)
        cI = NULL;
 
        /* render u and v change */
-       rc = colorize(ntscIm, markIm, NULL, NULL, 5, 1, 0);
+       rc = colorize(I, mI, NULL, NULL, 5, 1, 0, feat_names);
        if (rc < 0) {
                printerror("No memory! Use smaller image or add more memory.");
                goto error;
        }
 
-       /* if we have a change, we apply brightness+contrast from ntscIm */
-       if (change_bc) {
-               ptr = darrayGetPr(ntscIm);
-               ptr2 = darrayGetPr(ntscIm);
-               for (i = 0; i < img_height; i++) {
-                       for (j = 0; j < img_width; j++) {
-                               /* apply contrast */
-                               ptr2[width * i + j] = (ptr2[width * i + j] - 0.5) * ptr[width * height * 4 + width * i + j] * 10.0 + 0.5;
-                               /* apply brightness */
-                               ptr2[width * i + j] += ptr[width * height * 3 + width * i + j] * 10.0;
-                               if (ptr2[width * i + j] < 0)
-                                       ptr2[width * i + j] = 0;
-                               if (ptr2[width * i + j] > 1)
-                                       ptr2[width * i + j] = 1;
-                       }
-               }
-       }
+       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);
 
        if (img_scale_y == img_scale_x*2)
                zoom_field = 2;
        else
                zoom_field = 1;
 
-       /* apply YUV to pixbuffer and display */
-       pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, img_width, img_height * zoom_field);
-       ptr = darrayGetPr(ntscIm);
-       yuv2rgb(ptr, ptr, width, height);
+       /* convert YUV to RGB */
+       pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height * zoom_field);
+       yuv2rgb(ptr_y, ptr_y, width, height);
+
+       /* private structure */
+       cp = calloc(sizeof(struct colorize_priv), 1);
+       cp->width = width*zoom_field;
+       cp->height = height*zoom_field;
+       cp->alpha = change_alpha;
+
+       /* apply image to be saved later */
+       cp->img = malloc(width*height*(3+change_alpha)*sizeof(unsigned short));
+       array2img_short(ptr_y, width, height, cp->img, width, height, change_alpha);
+
+       /* create image */
+       if (change_alpha) {
+               /* simulate alpha by pattern */
+               double pat, a;
+               for (i = 0; i < height; i++) {
+                       for (j = 0; j < width; j++) {
+                               pat = (((j>>3)&1) == ((i>>3)&1)) ? 0.5 : 0.75;
+                               a = ptr_a[i*width+j];
+                               /* yuv is actually RGB */
+                               ptr_y[i*width+j] = a * ptr_y[i*width+j] + (1.0 - a) * pat;
+                               ptr_u[i*width+j] = a * ptr_u[i*width+j] + (1.0 - a) * pat;
+                               ptr_v[i*width+j] = a * ptr_v[i*width+j] + (1.0 - a) * pat;
+                       }
+               }
+       }
        data = gdk_pixbuf_get_pixels(pixbuf);
        rs = gdk_pixbuf_get_rowstride(pixbuf);
-       for (i = 0; i < img_height*zoom_field; i++) {
-               for (j = 0; j < img_width; j++) {
-                       c = ptr[(i/zoom_field)*width+j] * 255.0F;
+       for (i = 0; i < height*zoom_field; i++) {
+               for (j = 0; j < width; j++) {
+                       /* yuv is actually RGB */
+                       c = ptr_y[(i/zoom_field)*width+j] * 255.0F;
                        if (c < 0)
                                c = 0;
                        else if (c > 255)
                                c = 255;
                        data[i*rs + 3*j + 0] = c;
-                       c = ptr[(i/zoom_field)*width+j + width*height] * 255.0F;
+                       c = ptr_u[(i/zoom_field)*width+j] * 255.0F;
                        if (c < 0)
                                c = 0;
                        else if (c > 255)
                                c = 255;
                        data[i*rs + 3*j + 1] = c;
-                       c = ptr[(i/zoom_field)*width+j + width*height*2] * 255.0F;
+                       c = ptr_v[(i/zoom_field)*width+j] * 255.0F;
                        if (c < 0)
                                c = 0;
                        else if (c > 255)
@@ -306,20 +257,16 @@ void colorize_image(void)
                }
        }
 
-       /* create image */
        image = gtk_image_new_from_pixbuf(pixbuf);
        gtk_widget_show(image);
 
-       darrayDestroy(markIm);
-       markIm = NULL;
-       darrayDestroy(ntscIm);
-       ntscIm = NULL;
+       darrayDestroy(mI);
+       mI = NULL;
+       darrayDestroy(I);
+       I = NULL;
 
        darrayDone();
 
-       /* private structure */
-       cp = calloc(sizeof(struct colorize_priv), 1);
-
        /* create window */
        colorize_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(colorize_window), "Colorized");
@@ -328,8 +275,6 @@ void colorize_image(void)
 
        cp->window = colorize_window;
        cp->pixbuf = pixbuf;
-       cp->width = img_width*zoom_field;
-       cp->height = img_height*zoom_field;
        p = frame_list[timeline_selected].filename;
        while((q = strchr(p, DIR_SEPERATOR)))
                p = q + 1;
@@ -371,8 +316,8 @@ void colorize_image(void)
 error:
        darrayDestroy(gI);
        darrayDestroy(cI);
-       darrayDestroy(markIm);
-       darrayDestroy(ntscIm);
+       darrayDestroy(mI);
+       darrayDestroy(I);
 
        darrayDone();
 }
index 164fa61..c6b8180 100644 (file)
@@ -4,7 +4,7 @@
 #include <unistd.h>
 #include <math.h>
 #include "main.h"
-#include "../src/ppm.h"
+#include "../src/img.h"
 #include "../src/mark.h"
 #include "../src/yuv.h"
 #include "image.h"
@@ -29,7 +29,6 @@ extern int button_down_x, button_down_y;
 /* load image and create pixbuf */
 void create_image(const char *filename, int resize)
 {
-       int rc;
        static char imgfile[256];
 
        destroy_image();
@@ -48,8 +47,8 @@ void create_image(const char *filename, int resize)
                strcat(imgfile, p);
        } else
                strcpy(imgfile, filename);
-       rc = load_img(-1, &img_grey_buffer, &img_width, &img_height, imgfile, 0);
-       if (rc) {
+       img_grey_buffer = load_img(&img_width, &img_height, imgfile, 0);
+       if (!img_grey_buffer) {
                img_grey_buffer = NULL;
                if (!rendered)
                        printerror("Failed to load grey image '%s'", imgfile);
@@ -178,7 +177,7 @@ void draw_image(int x, int y, int w, int h)
        GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
        int window_width, window_height, x_offset, y_offset;
        gdk_drawable_get_size (draw, &window_width, &window_height);
-       double _r, _g, _b, _y, _u, _v, u_palette, v_palette;
+       double _r, _g, _b, _y, _u, _v, u_palette, v_palette, pat, alpha;
        int cr, cg, cb;
        int _c, preview_asis = 0;
 
@@ -332,14 +331,19 @@ void draw_image(int x, int y, int w, int h)
                                                cr = mark_palette[c-1].r;
                                                cg = mark_palette[c-1].g;
                                                cb = mark_palette[c-1].b;
-                                               if (cr == 255 && cg == 255 && cb == 255) {
-                                                       compose[j*3] = compose[j*3+1] = compose[j*3+2] = ((((i+y)>>3)&1) == (((j+x)>>3)&1)) ? 255 : 192;
-                                               } else
-                                               {
-                                                       compose[j*3] = cr;
-                                                       compose[j*3+1] = cg;
-                                                       compose[j*3+2] = cb;
+                                               alpha = mark_palette[c-1].alpha;
+                                               if (alpha < 1) {
+                                                       pat = ((((i+y)>>3)&1) == (((j+x)>>3)&1)) ? 192.0 : 128.0;
+                                                       _r = (double)cr * alpha + pat * (1-alpha);
+                                                       _g = (double)cg * alpha + pat * (1-alpha);
+                                                       _b = (double)cb * alpha + pat * (1-alpha);
+                                                       cr = _r;
+                                                       cg = _g;
+                                                       cb = _b;
                                                }
+                                               compose[j*3] = cr;
+                                               compose[j*3+1] = cg;
+                                               compose[j*3+2] = cb;
                                        }
                                }
                        }
index 667214f..4b9624b 100644 (file)
@@ -13,7 +13,7 @@ int mark_selected = 0;
 #define COLOR_WIDTH 100
 #define COLOR_HEIGHT 20
 
-char *bc_pic[] = {
+static char *bc_pic[] = {
        "     *     ",
        " *   *   * ",
        "  *     *  ",
@@ -26,20 +26,35 @@ char *bc_pic[] = {
        " *   *   * ",
        "     *     ",
 };
+
+static char *alpha_pic[] = {
+       "   ***    *",
+       "  *   *   *",
+       " *     * * ",
+       " *     * * ",
+       "*       *  ",
+       "*       *  ",
+       "*       *  ",
+       " *     **  ",
+       " *     **  ",
+       "  *   *  * ",
+       "   ***    *",
+};
 static GdkPixbuf *draw_pixpuf(int i)
 {
        GdkPixbuf *pixbuf;
        guchar *data;
-       int j, k, rs;
+       int j, jj, k, kk, rs;
        int cr, cg, cb;
-       float bright, contrast;
-       double r, g, b, y, u, v;
+       float bright, contrast, alpha;
+       double r, g, b, y, u, v, pat;
 
        cr = mark_palette[i].r;
        cg = mark_palette[i].g;
        cb = mark_palette[i].b;
        bright = mark_palette[i].bright;
        contrast = mark_palette[i].contrast;
+       alpha = mark_palette[i].alpha;
        r = cr / 255.0;
        g = cg / 255.0;
        b = cb / 255.0;
@@ -68,6 +83,10 @@ static GdkPixbuf *draw_pixpuf(int i)
                                if (y > 1)
                                        y = 1;
                                yuv2rgb_pixle(y, u, v, &r, &g, &b);
+                               pat = ((k>>3)&1) ? 0.5 : 0.75;
+                               r = r * alpha + pat * (1-alpha);
+                               g = g * alpha + pat * (1-alpha);
+                               b = b * alpha + pat * (1-alpha);
                                cr = r * 255.0F;
                                if (cr < 0)
                                        cr = 0;
@@ -97,6 +116,19 @@ static GdkPixbuf *draw_pixpuf(int i)
                }
        }
 
+       /* indicate a change in alpha */
+       if (alpha < 1) {
+               for (k = 0, kk = COLOR_HEIGHT - 11; k < 11; k++, kk++) {
+                       for (j = 0, jj = COLOR_HEIGHT - 11; j < 11; j++, jj++) {
+                               if (alpha_pic[j][k] == '*') {
+                                       data[jj * rs + kk * 3 + 0] = 255;
+                                       data[jj * rs + kk * 3 + 1] = 0;
+                                       data[jj * rs + kk * 3 + 2] = 0;
+                               }
+                       }
+               }
+       }
+
        /* indicate a change in brightness + contrast */
        if (bright != 0 || contrast != 1) {
                for (k = 0; k < 11; k++) {
@@ -128,6 +160,7 @@ void create_palette(void)
                mark_palette[i].b = 0;
                mark_palette[i].bright = 0;
                mark_palette[i].contrast = 1;
+               mark_palette[i].alpha = 1;
        }
 
        strcpy(mark_palette[0].name, "red");
index 25ca678..88ab413 100644 (file)
@@ -284,7 +284,7 @@ error:
        return rc;
 }
 
-int colorize_solve(struct colorize *col, int quick)
+int colorize_solve(struct colorize *col, int quick, char **feat_names)
 {
        int z, d, c, ww, hh, kk;
        int rc = -1;
@@ -295,7 +295,7 @@ int colorize_solve(struct colorize *col, int quick)
                int pixles, j;
                double *value_ptr, *init_ptr, *mark_ptr;
 
-               printf(" #%d", c); fflush(stdout);
+               printf(" #%d(%s)", c, feat_names[c-1]); fflush(stdout);
                /* apply component
                 * - copy component into value array (level 0), otherwise 0
                 * - use maked colors for init array, otherwise use 0
@@ -481,7 +481,7 @@ void colorize_free(struct colorize *col)
        darrayDestroy(col->init);
 }
 
-int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, int scalexyz)
+int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, int scalexyz, char **feat_names)
 {
        struct colorize col;
        int rc = -1;
@@ -499,7 +499,7 @@ int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *
        if (rc < 0)
                goto error;
 
-       rc = colorize_solve(&col, 0);
+       rc = colorize_solve(&col, 0, feat_names);
        if (rc < 0)
                goto error;
 
index 295bf36..f37e30b 100644 (file)
@@ -23,8 +23,8 @@ struct colorize {
 };
 
 int colorize_prepare(struct colorize *col);
-int colorize_solve(struct colorize *col, int quick);
+int colorize_solve(struct colorize *col, int quick, char **feat_names);
 void colorize_free(struct colorize *col);
 
-int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, int scalexyz);
+int colorize(const darray_t *image, const darray_t *image_mark, const darray_t *flow, const darray_t *flow_i, int inner_iter, int outer_iter, int scalexyz, char **feat_names);
 #endif
index aed5911..2be2e7a 100644 (file)
@@ -97,6 +97,8 @@ error:
 #ifdef DEBUG_ARRAY
        printf("darray: No memory to allocate (used %lu Mbytes)\n", arraysize/1024/1024);
        sleep(2);
+#else
+       printf("%s: failed to allocate memory\n", __func__);
 #endif
        return NULL;
 }
index cb94293..15d80af 100644 (file)
@@ -20,7 +20,8 @@ bin_PROGRAMS = \
 
 colorize_SOURCES = \
        colorize.c \
-       ppm.c \
+       process.c \
+       img.c \
        yuv.c \
        mark.c
 if ENABLE_OPENCV
index db604f7..dd3df42 100644 (file)
@@ -7,16 +7,15 @@
 #include <time.h>
 #include "../lib/darray.h"
 #include "../lib/colorize.h"
-#include "ppm.h"
+#include "img.h"
 #include "yuv.h"
 #include "mark.h"
+#include "process.h"
 #include "dir_seperator.h"
 #ifdef WITH_OPENCV
 #include "opticalflow.h"
 #endif
 
-#define min(x,y) ((x < y) ? x : y)
-
 static void print_help(const char *app);
 static void print_test_help();
 
@@ -181,83 +180,13 @@ again:
 }
 
 /*
- * scaling
- */
-
-/* scale down image in img_buffer by calculating average */
-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;
-
-       if (scale == 1)
-               return;
-
-       w = width / scale;
-       h = height / scale;
-
-       for (i = 0; i < h; i++) {
-               for (j = 0; j < w; j++) {
-                       r = g = b = 0;
-                       for (y = 0; y < scale; y++) {
-                               for (x = 0; x < scale; x++) {
-                                       r += img_buffer[((i*scale+y) * width + j*scale+x) * 3 + 0];
-                                       g += img_buffer[((i*scale+y) * width + j*scale+x) * 3 + 1];
-                                       b += img_buffer[((i*scale+y) * width + j*scale+x) * 3 + 2];
-                               }
-                       }
-                       img_buffer[(i * w + j)*3 + 0] = r / scale / scale;
-                       img_buffer[(i * w + j)*3 + 1] = g / scale / scale;
-                       img_buffer[(i * w + j)*3 + 2] = b / scale / scale;
-               }
-       }
-}
-
-/* scale down mark map in mark_buffer */
-static void scale_mark(unsigned char *mark_buffer, int width, int height, int scale)
-{
-       int w, h, i, j, x, y;
-       unsigned char c, temp;
-
-       if (scale == 1)
-               return;
-
-       w = width / scale;
-       h = height / scale;
-
-       for (i = 0; i < h; i++) {
-               for (j = 0; j < w; j++) {
-                       c = 0;
-                       /* always use one index other than 0, if there is any in an areaa to be shrinked */
-                       for (y = 0; y < scale; y++) {
-                               for (x = 0; x < scale; x++) {
-                                       temp = mark_buffer[(i*scale+y) * width + j*scale+x];
-                                       if (temp)
-                                               c = temp;
-                               }
-                       }
-                       mark_buffer[i * w + j] = c;
-               }
-       }
-}
-
-/*
  * options
  */
 
-static int in_itr_num = 5, out_itr_num = 1, optical_flow = 1, bright_contrast = 1;
+static int in_itr_num = 5, out_itr_num = 1, optical_flow = 1, bright_contrast = 1, alpha_change = 1;
 int scale = 1, scalexyz = 999;
 
-static enum test {
-       NO_TEST = 0,
-       FLOW_NEXT,
-       FLOW_PREV,
-       MARKED,
-       MASK,
-       MASK_COLOR,
-       BC_ONLY,
-       BC_IMAGE,
-} test = NO_TEST;
+static enum test test = NO_TEST;
 
 static int parse_test(const char *arg)
 {
@@ -281,6 +210,12 @@ static int parse_test(const char *arg)
                return BC_ONLY;
        if (!strcmp(arg, "bc-image"))
                return BC_IMAGE;
+       if (!strcmp(arg, "alpha"))
+               return ALPHA;
+       if (!strcmp(arg, "no-alpha"))
+               return NO_ALPHA;
+       if (!strcmp(arg, "removal-image"))
+               return REMOVAL_IMAGE;
 
        return NO_TEST;
 }
@@ -333,6 +268,10 @@ static int handle_options(int argc, char **argv)
                        bright_contrast = atoi(optarg);
                        skip_args += 2;
                        break;
+               case 'a':
+                       alpha_change = atoi(optarg);
+                       skip_args += 2;
+                       break;
                case 'f':
                        optical_flow = atoi(optarg);
                        skip_args += 2;
@@ -367,7 +306,7 @@ static void print_help(const char *app)
 #include "../version.h"
        );
        printf("Usage: %s [options] <grey ppm image> <marked ppm image> <result ppm image> [<frames> <start>]\n", app);
-       printf("       Colorize grey image using maked image and save to result image.\n");
+       printf("       Colorize grey image using marked image and save to result image.\n");
        printf("       If frames and start frame is given, image names must include printf integer formatting (e.g. %%04d).\n");
        printf("Usage: %s [options] <grey ppm image> marked <result ppm image>\n", app);
        printf("       Colorize grey image using marked mask + palette and save to result image.\n");
@@ -385,6 +324,7 @@ static void print_help(const char *app)
        else
                printf("(default=infinite)\n");
        printf(" -b --brightness-contrast [0 | 1]    Apply brightnes and contrast, if defined in palette by GUI (default=%d)\n", bright_contrast);
+       printf(" -a --alpha-change [0 | 1]           Apply alpha channel change, if defined in palette by GUI (default=%d)\n", alpha_change);
 #ifdef WITH_OPENCV
        printf(" -f --optical-flow [0 | 1]           Apply optical flow, if defined by GUI (default=%d)\n", optical_flow);
 #endif
@@ -399,11 +339,14 @@ static void print_test_help()
        printf("           flow-next     Optical flow plane to next image\n");
        printf("           flow-prev     Optical flow plane to previous image\n");
 #endif
-       printf("           marked        Only apply makred colors to grey image\n");
+       printf("           marked        Only apply marked colors to grey image\n");
        printf("           mask          Show mask of marked areas\n");
        printf("           mask+color    Show mask of marked areas + color\n");
        printf("           bc-only       Only apply brightness+contrast, leave colors of grey image as is\n");
        printf("           bc-image      Show brightness+contrast change on grey image as uv components\n");
+       printf("           alpha         Show the image with alpha channel only\n");
+       printf("           no-alpha      Show the image without alpha channel, to see pixles that are made transparent\n");
+       printf("           removal-image Show the image with \"transparency removal layer\" only, but keep u and v\n");
 }
 
 /*
@@ -412,20 +355,21 @@ static void print_test_help()
 
 int main(int argc, char *argv[])
 {
-       darray_t *gI = NULL, *cI = NULL, *markIm = NULL, *ntscIm = NULL;
+       darray_t *gI = NULL, *cI = NULL, *mI = NULL, *I = NULL;
        darray_t *flow = NULL, *flow_i = NULL;
-       double *ptr, *ptr2, *ptr3;
+       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;
        double diff, sum;
        int dims[4];
        int w = 0, h = 0, load_w, load_h, k = 1, index = 0, z;
-       unsigned short *img_buffer, *img_buffer_all = NULL;
+       unsigned short *img = NULL;
        unsigned char *mark_buffer = NULL;
        int rc, x, y, i, ii;
        time_t start, end;
        const char* filename;
        char first_filename[256];
        int seq_offset = 0, seq_next = 0;
-       int features, change_bc;
+       int features, change_bc, change_alpha;
+       char *feat_names[20];
        int skip_args;
 
        skip_args = handle_options(argc, argv);
@@ -464,7 +408,7 @@ next_sequence:
 
        time(&start);
 
-       change_bc = 0;
+       change_bc = change_alpha = 0;
        for (z = 0; z < k; z++) {
                if (sequence) {
                        filename = sequence[z].filename;
@@ -475,10 +419,9 @@ next_sequence:
                }
 #ifdef WITH_OPENCV
                // load flow settings
-               if (sequence || !strcmp(argv[2], "marked")) {
+               if (sequence && optical_flow) {
                        flow_default();
-                       if (optical_flow)
-                               load_flow(first_filename);
+                       load_flow(first_filename);
                        if (flow_enable == 0 && (test == FLOW_NEXT || test == FLOW_PREV)) {
                                fprintf(stderr, "Cannot test optical flow, because it is not enabled by GUI.\n");
                                exit (0);
@@ -486,12 +429,12 @@ next_sequence:
                }
 #endif
                // load original image and convert their RGB components to double RGB array
-               rc = load_img(-1, &img_buffer, &load_w, &load_h, filename, index + z);
-               if (rc) {
+               img = load_img(&load_w, &load_h, filename, index + z);
+               if (!img) {
                        fprintf(stderr, "Failed to load grey image '%s'\n", filename);
                        return 0;
                }
-               scale_img(img_buffer, load_w, load_h, scale);
+               scale_img(img, load_w, load_h, scale);
                if (z == 0) {
                        w = load_w / scale;
                        h = load_h / scale;
@@ -517,20 +460,8 @@ next_sequence:
                        printf("failed to create marked image array\n");
                        exit (0);
                }
-               ptr = darrayGetPr(gI) + w*h*3*z;
-               img2array(img_buffer, w, h, ptr, w, h);
-#ifdef WITH_OPENCV
-               if (k > 1 && flow_enable) {
-                       if (!img_buffer_all)
-                               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);
-                       }
-                       memcpy(img_buffer_all + w*h*3*z, img_buffer, w*h*3*sizeof(unsigned short));
-               }
-#endif
-               free(img_buffer);
+               img2array_short(img, w, h, darrayGetPr(gI) + w*h*3*z, w, h);
+               free(img);
 
                if (sequence || !strcmp(argv[2], "marked")) {
                        char name[256];
@@ -552,7 +483,7 @@ next_sequence:
                        /* always load full unscaled image, then scale down */
                        if (load_marked(mark_buffer + w*h*z, load_w, load_h, name) == 0) {
                                scale_mark(mark_buffer + w*h*z, load_w, load_h, scale);
-                               ptr = darrayGetPr(cI) + w*h*3*z;
+                               ptr_cI = darrayGetPr(cI) + w*h*3*z;
                                for (y = 0; y < h; y++) {
                                        for (x = 0; x < w; x++) {
                                                /* do not apply mask on index 0 */
@@ -562,27 +493,30 @@ next_sequence:
                                                /* check for any brightness/contrast change */
                                                if (bright_contrast && (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1))
                                                        change_bc = 1;
+                                               /* check for any alpha change */
+                                               if (alpha_change && mark_palette[c-1].alpha < 1)
+                                                       change_alpha = 1;
                                                /* do not apply white pixles, this meas: keep original color */
                                                if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
                                                        continue;
-                                               ptr[y*w+x] = mark_palette[c-1].r / 255.0F;
-                                               ptr[y*w+x + w*h] = mark_palette[c-1].g / 255.0F;
-                                               ptr[y*w+x + w*h*2] = mark_palette[c-1].b / 255.0F;
+                                               ptr_cI[y*w+x] = mark_palette[c-1].r / 255.0F;
+                                               ptr_cI[y*w+x + w*h] = mark_palette[c-1].g / 255.0F;
+                                               ptr_cI[y*w+x + w*h*2] = mark_palette[c-1].b / 255.0F;
                                        }
                                }
                        } else
                                memset(mark_buffer + w*h*z, 0, w*h);
                } else {
                        // load marked image and convert their RGB components to double YUV array
-                       rc = load_img(-1, &img_buffer, &load_w, &load_h, argv[2], index + z);
-                       if (!rc) {
+                       img = load_img(&load_w, &load_h, argv[2], index + z);
+                       if (!img) {
+                               scale_img(img, load_w, load_h, scale);
                                if (load_w/scale != w || load_h/scale != h) {
                                        fprintf(stderr, "Error: All input images must have equal dimenstions.\n");
                                        return 0;
                                }
-                               ptr = darrayGetPr(cI) + w*h*3*z;
-                               img2array(img_buffer, w, h, ptr, w, h);
-                               free(img_buffer);
+                               img2array_short(img, w, h, darrayGetPr(cI) + w*h*3*z, w, h);
+                               free(img);
                        } else {
                                fprintf(stderr, "Failed to load marked image, omitting...\n");
                                memcpy(darrayGetPr(cI) + w*h*3*z, darrayGetPr(gI) + w*h*3*z, w*h*3 * sizeof(double));
@@ -590,37 +524,31 @@ next_sequence:
                }
        }
 
-       /* create color mask and ntsc arrays for the colorization process */
-       dims[0] = w; dims[1] = h; dims[2] = k;
-       markIm = darrayCreate(3, dims);
-       if (!markIm) {
-               printf("failed to create mark array\n");
-               exit (0);
-       }
-       features = (change_bc) ? 4 : 2;
-       dims[0] = w; dims[1] = h; dims[2] = features+1; dims[3] = k;
-       ntscIm = darrayCreate(4, dims);
-       if (!ntscIm) {
-               printf("failed to create ntsc array\n");
-               exit (0);
-       }
+       rc = alloc_I_arrays(&I, &mI, w, h, k, &features, feat_names, change_alpha, change_bc);
+       if (rc)
+               exit(0);
 
        for (z = 0; z < k; z++) {
+               set_I_ptr(I, mI, w, h, z, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
+               ptr_gI = darrayGetPr(gI) + w*h*3*z;
+               ptr_cI = darrayGetPr(cI) + w*h*3*z;
+
+               // convert original image into YUV
+               rgb2yuv(ptr_gI, ptr_gI, w, h);
+               // convert maked image into YUV
+               rgb2yuv(ptr_cI, ptr_cI, w, h);
+
                if (sequence || !strcmp(argv[2], "marked")) {
                        unsigned char c;
-                       ptr = darrayGetPr(markIm) + w*h*z;
                        // use marked mask to fill markIm
                        for (y = 0; y < h; y++) {
                                for (x = 0; x < w; x++) {
-                                       if (x < w && y < h) {
-                                               /* do not apply mask on index 0 */
-                                               c = mark_buffer[y*w+x + w*h*z];
-                                       } else
-                                               c = 0;
+                                       /* do not apply mask on index 0 */
+                                       c = mark_buffer[y*w+x + w*h*z];
                                        if (c)
-                                               ptr[y*w+x] = 1.0F;
+                                               ptr_m[y*w+x] = 1.0F;
                                        else
-                                               ptr[y*w+x] = 0.0F;
+                                               ptr_m[y*w+x] = 0.0F;
                                }
                        }
                } else {
@@ -629,100 +557,32 @@ next_sequence:
                        // - convert into absolute (positive values)
                        // - sum all components to get grey image
                        // - apply threshold (pixle is 1F, if the absolute difference is > 0.01F)
-                       // original code: markIm=(sum(abs(gI-cI),3)>0.01);
-                       ptr = darrayGetPr(gI) + w*h*3*z;
-                       ptr2 = darrayGetPr(cI) + w*h*3*z;
-                       ptr3 = darrayGetPr(markIm) + w*h*z;
+                       // original code: markIm=(sum(abs(gI-cI),3)>0.01); (according to developers of the algorithm)
                        for (i = 0, ii = w * h; i < ii; i++) {
                                diff = 0;
-                               sum = ptr[i] - ptr2[i];
+                               sum = ptr_gI[i] - ptr_cI[i];
                                if (sum < 0)
                                        diff -= sum;
                                else
                                        diff += sum;
-                               sum = ptr[i + ii] - ptr2[i + ii];
+                               sum = ptr_gI[i + ii] - ptr_cI[i + ii];
                                if (sum < 0)
                                        diff -= sum;
                                else
                                        diff += sum;
-                               sum = ptr[i + ii + ii] - ptr2[i + ii + ii];
+                               sum = ptr_gI[i + ii + ii] - ptr_cI[i + ii + ii];
                                if (sum < 0)
                                        diff -= sum;
                                else
                                        diff += sum;
                                if (diff > 0.01)
-                                       ptr3[i] = 1.0F;
+                                       ptr_m[i] = 1.0;
                                else
-                                       ptr3[i] = 0.0F;
-                       }
-               }
-
-               // convert original image into YUV
-               ptr = darrayGetPr(gI) + w*h*3*z;
-               rgb2yuv(ptr, ptr, w, h);
-
-               // convert maked image into YUV
-               ptr = darrayGetPr(cI) + w*h*3*z;
-               rgb2yuv(ptr, ptr, w, h);
-
-               if (test != BC_ONLY) {
-                       if (sequence || !strcmp(argv[2], "marked")) {
-                               unsigned char c;
-                               // generate NTSC image: use luminance from original image and chrominance from original or marked image
-                               ptr = darrayGetPr(gI) + w*h*3*z;
-                               ptr2 = darrayGetPr(cI) + w*h*3*z;
-                               ptr3 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                               /* use original y component */
-                               memcpy(ptr3, ptr, w * h * sizeof(double));
-                               /* apply new uv components */
-                               for (y = 0; y < h; y++) {
-                                       for (x = 0; x < w; x++) {
-                                               c = mark_buffer[y*w+x + w*h*z];
-                                               if (c == 0) {
-                                                       ptr3[w * h + w * y + x] = ptr[w * h + w * y + x];
-                                                       ptr3[w * h * 2 + w * y + x] = ptr[w * h * 2 + w * y + x];
-                                               } else {
-                                                       ptr3[w * h + w * y + x] = ptr2[w * h + w * y + x];
-                                                       ptr3[w * h * 2 + w * y + x] = ptr2[w * h * 2 + w * y + x];
-                                               }
-                                       }
-                               }
-                       } else {
-                               // generate NTSC image: use luminance from original image and chrominance from maked image
-                               ptr = darrayGetPr(gI) + w*h*3*z;
-                               ptr2 = darrayGetPr(cI) + w*h*3*z;
-                               ptr3 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                               memcpy(ptr3, ptr, w * h * sizeof(double));
-                               memcpy(ptr3 + w * h, ptr2 + w * h, w * h * sizeof(double));
-                               memcpy(ptr3 + w * h * 2, ptr2 + w * h * 2, w * h * sizeof(double));
+                                       ptr_m[i] = 0.0;
                        }
-               } else {
-                       /* use grey image as result if BC_ONLY test is selected */
-                       ptr = darrayGetPr(gI) + w*h*3*z;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       memcpy(ptr2, ptr, w * h * 3 * sizeof(double));
                }
 
-               if (change_bc) {
-                       unsigned char c;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       /* use original y component */
-                       memcpy(ptr2, ptr, w * h * sizeof(double));
-                       /* apply brightness and contrast from makred pixles to uv components of grey image */
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       /* use unchanged brightness and contrast on index 0 */
-                                       c = mark_buffer[y*w+x + w*h*z];
-                                       if (c == 0) {
-                                               ptr2[y*w+x + w*h*3] = 0;
-                                               ptr2[y*w+x + w*h*4] = 0.1;
-                                       } else {
-                                               ptr2[y*w+x + w*h*3] = mark_palette[c-1].bright / 10.0;
-                                               ptr2[y*w+x + w*h*4] = mark_palette[c-1].contrast / 10.0;
-                                       }
-                               }
-                       }
-               }
+               prepare_arrays(w, h, change_alpha, change_bc, mark_buffer+w*h*z, ptr_gI, ptr_cI, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, test);
        }
 
 #ifdef WITH_OPENCV
@@ -744,16 +604,14 @@ next_sequence:
                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);
+                       create_flow_maps(NULL, darrayGetPr(gI) + w*h*3*(z+1), darrayGetPr(gI) + w*h*3*z, w, h, flow_window/scale, 0, NULL, NULL, darrayGetPr(flow) + w*h*z, darrayGetPr(flow) + w*h*z + w*h*(k-1), NULL);
                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);
+                       create_flow_maps(darrayGetPr(gI) + w*h*3*z, NULL, darrayGetPr(gI) + w*h*3*(z+1), w, h, flow_window/scale, 0, darrayGetPr(flow_i) + w*h*z, darrayGetPr(flow_i) + w*h*z + w*h*(k-1), NULL, NULL, NULL);
        }
 #else
        if (k > 1)
                printf("Note: Optical flow is not compiled in!\n");
 #endif
-       free(img_buffer_all);
-       img_buffer_all = NULL;
 
        darrayDestroy(gI);
        gI = NULL;
@@ -762,7 +620,7 @@ next_sequence:
 
        if (test != FLOW_NEXT && test != FLOW_PREV && test != MARKED && test != MASK && test != MASK_COLOR && test != BC_ONLY && test != BC_IMAGE) {
                printf("Colorizing %d frames, please wait...\n", k);
-               rc = colorize(ntscIm, markIm, flow, flow_i, in_itr_num, out_itr_num, scalexyz);
+               rc = colorize(I, mI, flow, flow_i, in_itr_num, out_itr_num, scalexyz, feat_names);
                if (rc < 0) {
                        if (k > 1)
                                printf("No memory! Use smaller frames or less frames between key frames or add more memory.");
@@ -772,124 +630,44 @@ next_sequence:
                }
        }
 
-       /* if we have a change, we apply brightness+contrast from ntscIm */
-       if (change_bc) {
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       /* apply contrast */
-                                       ptr2[w * y + x] = (ptr2[w * y + x] - 0.5) * ptr[w * h * 4 + w * y + x] * 10.0 + 0.5;
-                                       /* apply brightness */
-                                       ptr2[w * y + x] += ptr[w * h * 3 + w * y + x] * 10.0;
-                                       if (ptr2[w * y + x] < 0)
-                                               ptr2[w * y + x] = 0;
-                                       if (ptr2[w * y + x] > 1)
-                                               ptr2[w * y + x] = 1;
-#if 0
-#warning TEST: show brightness and contrast change as uv vectors on a grey array */
-ptr2[w * y + x] = 0.5;
-ptr2[w * h + w * y + x] = ptr[w * h + w * y + x] * 10;
-ptr2[w * h * 2 + w * y + x] = ptr[w * h * 2 + w * y + x] * 10 - 1;
-#endif
-                               }
-                       }
-               }
-       }
+       for (z = 0; z < k; z++) {
+               set_I_ptr(I, mI, w, h, z, features, change_alpha, change_bc, &ptr_y, &ptr_u, &ptr_v, &ptr_a, &ptr_r, &ptr_b, &ptr_c, &ptr_m);
+               postpare_arrays(w, h, change_alpha, change_bc, ptr_y, ptr_u, ptr_v, ptr_a, ptr_r, ptr_b, ptr_c, ptr_m, test);
 
 #ifdef WITH_OPENCV
-       if (test == FLOW_NEXT || test == FLOW_PREV) {
-               /* apply flow planes to result image as u and y vector */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
+               if (test == FLOW_NEXT || test == FLOW_PREV) {
+                       double *ptr_f1 = NULL, *ptr_f2 = NULL;
+                       /* apply flow planes to result image as u and y vector */
                        if (test == FLOW_NEXT) {
-                               ptr2 = darrayGetPr(flow) + w*h*z;
-                               ptr3 = darrayGetPr(flow) + w*h*z*(k-1);
+                               if (flow) {
+                                       ptr_f1 = darrayGetPr(flow) + w*h*z;
+                                       ptr_f2 = darrayGetPr(flow) + w*h*z*(k-1);
+                               }
                        } else {
-                               ptr2 = darrayGetPr(flow_i) + w*h*z;
-                               ptr3 = darrayGetPr(flow_i) + w*h*z*(k-1);
+                               if (flow_i) {
+                                       ptr_f1 = darrayGetPr(flow_i) + w*h*z;
+                                       ptr_f2 = darrayGetPr(flow_i) + w*h*z*(k-1);
+                               }
                        }
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       ptr[w * y + x] = 0.5;
-                                       if (z < k-1) {
-                                               ptr[w * y + x + w*h] = ptr2[w * y + x] / 50;
-                                               ptr[w * y + x + w*h*2] = ptr3[w * y + x] / 50;
-                                       } else {
-                                               ptr[w * y + x + w*h] = 0;
-                                               ptr[w * y + x + w*h*2] = 0;
+                       if (ptr_f1 && ptr_f1) {
+                               for (y = 0; y < h; y++) {
+                                       for (x = 0; x < w; x++) {
+                                               ptr_y[w*y+x] = 0.5;
+                                               if (z < k-1) {
+                                                       ptr_u[w*y+x] = ptr_f1[w * y + x] / 50;
+                                                       ptr_v[w*y+x] = ptr_f2[w * y + x] / 50;
+                                               } else {
+                                                       ptr_u[w*y+x] = 0;
+                                                       ptr_v[w*y+x] = 0;
+                                               }
                                        }
                                }
                        }
                }
-       }
 #endif
 
-       if (test == MASK) {
-               /* apply maked mask as image */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(markIm) + w*h*z;
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       ptr[w * y + x] = ptr2[w * y + x];
-                                       ptr[w * y + x + w*h] = ptr2[w * y + x];
-                                       ptr[w * y + x + w*h*2] = ptr2[w * y + x];
-                               }
-                       }
-               }
-       }
-
-       if (test == MASK_COLOR) {
-               /* apply maked mask on grey image */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(markIm) + w*h*z;
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       /* darken unmarked areas, make maked areas with uniformed brightness */
-                                       if (ptr2[w * y + x] < 0.5F)
-                                               ptr[w * y + x] = ptr[w * y + x] / 4;
-                                       else
-                                               ptr[w * y + x] = 0.5F;
-                               }
-                       }
-               }
-       }
-
-       if (test == BC_IMAGE) {
-               /* apply bc image as result image */
-               for (z = 0; z < k; z++) {
-                       ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                       /* use uniformed brightness as y component */
-                       for (y = 0; y < h; y++) {
-                               for (x = 0; x < w; x++) {
-                                       ptr[w * y + x] = 0.5F;
-                               }
-                       }
-                       if (change_bc) {
-                               ptr2 = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-                               memcpy(ptr+w*h, ptr2+w*h*3, w * h * sizeof(double));
-                               memcpy(ptr+w*h*2, ptr2+w*h*4, w * h * sizeof(double));
-                       } else {
-                               memset(ptr+w*h, 0, w * h * sizeof(double));
-                               memset(ptr+w*h*2, 0, w * h * sizeof(double));
-                       }
-               }
-       }
-
-       // save result YUV array to image with RGB components
-       img_buffer = (unsigned short *)malloc(w*h*3*sizeof(unsigned short));
-       if (!img_buffer) {
-               fprintf(stderr, "Failed to allocate image buffer\n");
-               return 0;
-       }
-       for (z = 0; z < k; z++) {
-               ptr = darrayGetPr(ntscIm) + w*h*(features+1)*z;
-               yuv2rgb(ptr, ptr, w, h);
-               array2img(ptr, w, h, img_buffer, w, h);
+               // save result YUV array to image with RGB components
+               yuv2rgb(ptr_y, ptr_y, w, h);
                if (sequence) {
                        static char name[256], *p, *q;
                        p = sequence[z].filename;
@@ -902,22 +680,25 @@ ptr2[w * h * 2 + w * y + x] = ptr[w * h * 2 + w * y + x] * 10 - 1;
                        filename = name;
                } else
                        filename = argv[3];
-               save_img(img_buffer, w, h, filename, index + z);
+               /* don't save alpha on these tests */
+               if (test == ALPHA || test == REMOVAL_IMAGE || test == NO_ALPHA)
+                       save_img_array(ptr_y, w, h, 0, filename, index + z);
+               else
+                       save_img_array(ptr_y, w, h, change_alpha, filename, index + z);
        }
-       free(img_buffer);
 
        time(&end);
        printf("Elapsed time: %d minutes, %d seconds\n", (int)(end-start)/60, (int)(end-start)%60);
 
        // destroy
-       darrayDestroy(ntscIm);
-       ntscIm = NULL;
+       darrayDestroy(I);
+       I = NULL;
+       darrayDestroy(mI);
+       mI = NULL;
        darrayDestroy(flow);
        flow = NULL;
        darrayDestroy(flow_i);
        flow_i = NULL;
-       darrayDestroy(markIm);
-       markIm = NULL;
 
        free(mark_buffer);
        mark_buffer = NULL;
diff --git a/src/img.c b/src/img.c
new file mode 100755 (executable)
index 0000000..a596c64
--- /dev/null
+++ b/src/img.c
@@ -0,0 +1,386 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "img.h"
+
+int save_depth = 16;
+
+#ifdef WITH_MAGICK
+#include <magick/api.h>
+
+/* load given image to memory. return short RGB values */
+unsigned short *load_img(int *width, int *height, const char *filename, int index)
+{
+       Image *image = NULL;
+       ImageInfo *imageinfo = NULL;
+       ExceptionInfo exception;
+       unsigned short *img = NULL;
+
+//     MagickCoreGenesis(NULL,MagickFalse);
+       InitializeMagick(NULL);
+       imageinfo = CloneImageInfo(0);
+       GetExceptionInfo(&exception);
+
+       sprintf(imageinfo->filename, filename, index);
+
+       image = ReadImage(imageinfo, &exception);
+       if (!image) {
+//             printf("failed to read image '%s' via *magick\n", filename);
+               goto exit;
+       }
+
+       *width = image->columns;
+       *height = image->rows;
+
+       img = (unsigned short *)malloc((*width) * (*height) * 3 * 2);
+       if (!img) {
+               printf("%s:failed to allocate image data\n", __func__);
+               goto exit;
+       }
+
+//     ExportImagePixels(image, 0, 0, *width, *height, "RGB", ShortPixel, darrayGetPr(darray), NULL);
+       DispatchImage(image, 0, 0, *width, *height, "RGB", ShortPixel, img, NULL);
+
+exit:
+       if (image)
+               DestroyImage(image);
+
+       if (imageinfo)
+               DestroyImageInfo(imageinfo);
+
+//     MagickCoreTerminus();
+       DestroyMagick();
+
+       return img;
+}
+
+/* save given image */
+int save_img(unsigned short *img, int width, int height, int alpha, const char *filename, int index)
+{
+       int rc = -1;
+       Image *image = NULL;
+       ImageInfo *imageinfo = NULL;
+       ExceptionInfo exception;
+
+//     MagickCoreGenesis(NULL,MagickFalse);
+       InitializeMagick(NULL);
+       imageinfo = CloneImageInfo(0);
+       GetExceptionInfo(&exception);
+
+       imageinfo->quality = 100;
+
+       image=ConstituteImage(width, height, (alpha)?"RGBA":"RGB", ShortPixel, img, &exception);
+       if (!image) {
+               printf("%s:failed to prepare to write image\n", __func__);
+               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("%s:failed to write image\n", __func__);
+               goto exit;
+       }
+
+       rc = 0;
+
+exit:
+       if (image)
+               DestroyImage(image);
+
+       if (imageinfo)
+               DestroyImageInfo(imageinfo);
+
+//     MagickCoreTerminus();
+       DestroyMagick();
+
+       return rc;
+}
+#else
+
+/* load given image to memory. return short RGB values */
+unsigned short *load_img(int *width, int *height, const char *filename, int index)
+{
+       FILE *fp = NULL;
+       unsigned short *img = NULL;
+       char line[256];
+       int words, i;
+
+       sprintf(line, filename, index);
+//     printf("reading image: %s\n", line);
+       fp = fopen(line, "r");
+       if (!fp) {
+//             printf("failed to read ppm image '%s'\n", filename);
+               goto exit;
+       }
+again1:
+       if (!fgets(line, sizeof(line), fp)) {
+               printf("%s:failed to read image depth\n", __func__);
+               goto exit;
+       }
+       line[sizeof(line)-1] = '\0';
+       if (line[0]) line[strlen(line)-1] = '\0';
+       if (line[0] == '#')
+               goto again1;
+       if (!!strcmp(line, "P6")) {
+               printf("%s:expecting image depth 'P6'\n", __func__);
+               goto exit;
+       }
+again2:
+       if (!fgets(line, sizeof(line), fp)) {
+               printf("%s:failed to read image size\n", __func__);
+               goto exit;
+       }
+       line[sizeof(line)-1] = '\0';
+       if (line[0]) line[strlen(line)-1] = '\0';
+       if (line[0] == '#')
+               goto again2;
+       sscanf(line, "%d %d", width, height);
+//     printf("Image size: w=%d h=%d\n", *width, *height);
+again3:
+       if (!fgets(line, sizeof(line), fp)) {
+               printf("%s:failed to read line '255' or '65535'\n", __func__);
+               goto exit;
+       }
+       line[sizeof(line)-1] = '\0';
+       if (line[0]) line[strlen(line)-1] = '\0';
+       if (line[0] == '#')
+               goto again3;
+       if (!strcmp(line, "255")) {
+               words = 1;
+       } else
+       if (!strcmp(line, "65535")) {
+               words = 2;
+       } else {
+               printf("%s:expecting line '255' or '65535'\n", __func__);
+               goto exit;
+       }
+
+       img = (unsigned short *)malloc((*width) * (*height) * 3 * 2);
+       if (!img) {
+               printf("%s:failed to allocate image data\n", __func__);
+               goto exit;
+       }
+       if (fread(img, (*width) * (*height) * 3 * words, 1, fp) != 1) {
+               printf("%s:failed to read image data\n", __func__);
+               goto exit;
+       }
+
+       /* char to short (255 -> 65535) */
+       if (words == 1) {
+               unsigned char *from = (unsigned char *)img, c;
+               for (i = (*width) * (*height) * 3 - 1; i >= 0; i--) {
+                       c = from[i];
+                       img[i] = (c << 8) | c;
+               }
+       } else {
+               /* correct byte order */
+               unsigned short v;
+               unsigned char *from = (unsigned char *)img;
+               for (i = 0; i < (*width) * (*height) * 3; i++) {
+                       v = ((*from++) << 8);
+                       v |= (*from++);
+                       img[i] = v;
+               }
+       }
+
+exit:
+       if (fp)
+               fclose(fp);
+
+       return img;
+}
+
+/* save given image */
+int save_img(unsigned short *img, int width, int height, int alpha, const char *filename, int index)
+{
+       FILE *fp = NULL;
+       int rc = -1;
+       char line[256];
+       int i;
+       unsigned short v;
+       unsigned char *to;
+
+       if (alpha) {
+               printf("%s:cannot save alpha component with PPM support only\n", __func__);
+               alpha = 0;
+               goto exit;
+       }
+
+       sprintf(line, filename, index);
+//     printf("writing image: %s\n", line);
+       fp = fopen(line, "w");
+       if (!fp) {
+               printf("%s:failed to write image\n", __func__);
+               goto exit;
+       }
+       fprintf(fp, "P6\n%d %d\n65535\n", width, height);
+
+       /* correct byte order, write and restore byte order */
+       to = (unsigned char *)img;
+       for (i = 0; i < width * height * 3; i++) {
+               v = img[i];
+               if (i/100*i == i) { printf("%04x ", v); }
+               (*to++) = v >> 8;
+               (*to++) = v;
+       }
+       rc = fwrite(img, width * height * 3 * 2, 1, fp);
+       to = (unsigned char *)img;
+       for (i = 0; i < width * height * 3; i++) {
+               v = (*to++) << 8;
+               v |= (*to++);
+               img[i] = v;
+       }
+       if (rc != 1) {
+               printf("%s:failed to write image data\n", __func__);
+               goto exit;
+       }
+
+       rc = 0;
+
+exit:
+       if (fp)
+               fclose(fp);
+
+       return rc;
+}
+#endif
+
+int save_img_array(double *array, int width, int height, int alpha, const char *filename, int index)
+{
+       int rc = -1;
+       unsigned short *img = NULL;
+       int components;
+
+#ifndef WITH_MAGICK
+       if (alpha) {
+               printf("%s:warning, cannot save alpha component with PPM support only\n", __func__);
+               alpha = 0;
+       }
+#endif
+       components = (alpha) ? 4 : 3;
+
+       img = (unsigned short *)malloc(width * height * components * 2);
+       if (!img) {
+               printf("%s:failed to allocate image data\n", __func__);
+               goto exit;
+       }
+
+       array2img_short(array, width, height, img, width, height, alpha);
+
+       save_img(img, width, height, alpha, filename, index);
+
+       rc = 0;
+
+exit:
+       if (img)
+               free(img);
+
+       return rc;
+}
+
+/* convert an image to a three dimensional array of double
+ * the size is: width, height, 3
+ */
+void img2array_short(unsigned short *img, int iw, int ih, double *array, int aw, int ah)
+{
+       int x, y;
+       int channel;
+       double r, g, b;
+
+       channel = aw * ah;
+
+       for (y = 0; y < ih; y++) {
+               for (x = 0; x < iw; x++) {
+                       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+channel] = g;
+                       array[x+aw*y+channel+channel] = b;
+               }
+       }
+}
+
+/* convert a three dimensional array of double to an image
+ * the size is: width, height, 3
+ */
+void array2img_short(double *array, int aw, int ah, unsigned short *img, int iw, int ih, int alpha)
+{
+       int x, y, c;
+       int channel, components;
+       double r, g, b, a;
+
+       channel = aw * ah;
+       components = (alpha) ? 4 : 3;
+
+       for (y = 0; y < ih; y++) {
+               for (x = 0; x < iw; x++) {
+                       r = array[x+aw*y];
+                       c = (r * 65535.0F + 0.5F);
+                       if (c < 0)
+                               c = 0;
+                       else if (c > 65535)
+                               c = 65535;
+                       img[(x+iw*y)*components] = c;
+                       g = array[x+aw*y+channel];
+                       c = (g * 65535.0F + 0.5F);
+                       if (c < 0)
+                               c = 0;
+                       else if (c > 65535)
+                               c = 65535;
+                       img[(x+iw*y)*components+1] = c;
+                       b = array[x+aw*y+channel+channel];
+                       c = (b * 65535.0F + 0.5F);
+                       if (c < 0)
+                               c = 0;
+                       else if (c > 65535)
+                               c = 65535;
+                       img[(x+iw*y)*components+2] = c;
+                       if (alpha) {
+                               a = array[x+aw*y+channel+channel+channel];
+                               c = (a * 65535.0F + 0.5F);
+                               if (c < 0)
+                                       c = 0;
+                               else if (c > 65535)
+                                       c = 65535;
+                               img[(x+iw*y)*components+3] = c;
+                       }
+               }
+       }
+}
+
+/*
+ * scale down image in img_buffer by calculating average
+ */
+void scale_img(unsigned short *img, int width, int height, int scale)
+{
+       int w, h, i, j, x, y;
+       int r, g, b;
+
+       if (scale == 1)
+               return;
+
+       w = width / scale;
+       h = height / scale;
+
+       for (i = 0; i < h; i++) {
+               for (j = 0; j < w; j++) {
+                       r = g = b = 0;
+                       for (y = 0; y < scale; y++) {
+                               for (x = 0; x < scale; x++) {
+                                       r += img[((i*scale+y) * width + j*scale+x) * 3 + 0];
+                                       g += img[((i*scale+y) * width + j*scale+x) * 3 + 1];
+                                       b += img[((i*scale+y) * width + j*scale+x) * 3 + 2];
+                               }
+                       }
+                       img[(i * w + j)*3 + 0] = r / scale / scale;
+                       img[(i * w + j)*3 + 1] = g / scale / scale;
+                       img[(i * w + j)*3 + 2] = b / scale / scale;
+               }
+       }
+}
+
+
diff --git a/src/img.h b/src/img.h
new file mode 100644 (file)
index 0000000..4541cdf
--- /dev/null
+++ b/src/img.h
@@ -0,0 +1,7 @@
+extern int save_depth;
+unsigned short *load_img(int *width, int *height, const char *filename, int index);
+int save_img(unsigned short *img, int width, int height, int alpha, const char *filename, int index);
+int save_img_array(double *array, int width, int height, int alpha, const char *filename, int index);
+void img2array_short(unsigned short *img, int iw, int ih, double *array, int aw, int ah);
+void array2img_short(double *array, int aw, int ah, unsigned short *img, int iw, int ih, int alpha);
+void scale_img(unsigned short *img, int width, int height, int scale);
index 0eb60c4..f3a6e11 100644 (file)
@@ -26,7 +26,7 @@ void save_palette(const char *filename)
                return;
        }
        for (i = 0; i < 255; i++)
-               fprintf(fp, "%03d %03d %03d \"%s\" %f %f\n", mark_palette[i].r, mark_palette[i].g, mark_palette[i].b, mark_palette[i].name, mark_palette[i].bright, mark_palette[i].contrast);
+               fprintf(fp, "%03d %03d %03d \"%s\" %f %f %f\n", mark_palette[i].r, mark_palette[i].g, mark_palette[i].b, mark_palette[i].name, mark_palette[i].bright, mark_palette[i].contrast, mark_palette[i].alpha);
        fprintf(fp, "blacklevel %f\n", black_level);
        fprintf(fp, "whitelevel %f\n", white_level);
        fprintf(fp, "fadelevel %f\n", fade_level);
@@ -42,7 +42,7 @@ int load_palette(const char *filename)
        FILE *fp;
        int i;
        int r, g, b;
-       float bright = 0, contrast = 1;
+       float bright, contrast, alpha;
 
        sprintf(name, "%s_palette", filename);
 //     printf("loading palette '%s'\n", name);
@@ -92,13 +92,17 @@ int load_palette(const char *filename)
                        *q = '\0';
                if ((p = strchr(p, '\"'))) {
                        p++;
-                       sscanf(p, "%f %f", &bright, &contrast);
+                       bright = 0;
+                       contrast = 1;
+                       alpha = 1;
+                       sscanf(p, "%f %f %f", &bright, &contrast, &alpha);
                }
                mark_palette[i].r = r;
                mark_palette[i].g = g;
                mark_palette[i].b = b;
                mark_palette[i].bright = bright;
                mark_palette[i].contrast = contrast;
+               mark_palette[i].alpha = alpha;
        }
        fclose(fp);
        return 0;
@@ -162,3 +166,31 @@ int load_marked(unsigned char *img_mark_buffer, int width, int height, const cha
        return 0;
 }
 
+/* scale down mark map in mark_buffer */
+void scale_mark(unsigned char *mark_buffer, int width, int height, int scale)
+{
+       int w, h, i, j, x, y;
+       unsigned char c, temp;
+
+       if (scale == 1)
+               return;
+
+       w = width / scale;
+       h = height / scale;
+
+       for (i = 0; i < h; i++) {
+               for (j = 0; j < w; j++) {
+                       c = 0;
+                       /* always use one index other than 0, if there is any in an areaa to be shrinked */
+                       for (y = 0; y < scale; y++) {
+                               for (x = 0; x < scale; x++) {
+                                       temp = mark_buffer[(i*scale+y) * width + j*scale+x];
+                                       if (temp)
+                                               c = temp;
+                               }
+                       }
+                       mark_buffer[i * w + j] = c;
+               }
+       }
+}
+
index 984c53d..aad7e4b 100644 (file)
@@ -4,6 +4,7 @@ struct mark_palette {
        unsigned char b;
        float bright;
        float contrast;
+       float alpha;
        char name[64];
 };
 
@@ -13,4 +14,5 @@ void save_palette(const char *filename);
 int load_palette(const char *filename);
 int save_marked(unsigned char *img_mark_buffer, int width, int height, const char *filename);
 int load_marked(unsigned char *img_mark_buffer, int width, int height, const char *filename);
+void scale_mark(unsigned char *mark_buffer, int width, int height, int scale);
 
index 0ea41ef..9a9b29d 100644 (file)
@@ -1,5 +1,5 @@
 #include <stdio.h>
-#include "ppm.h"
+#include "img.h"
 #include "opticalflow.h"
 #include "yuv.h"
 #include <opencv2/core/core_c.h>
@@ -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)
  *
  */
-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_maps(const double *img_prev_buffer, const double *img_next_buffer, const double *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;
@@ -169,26 +169,23 @@ void *create_flow_maps(const unsigned short *img_prev_buffer, const unsigned sho
        if (image_prev) {
                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] >> 8;
+                               CV_IMAGE_ELEM(image_prev, uchar, i, j) = img_prev_buffer[i*width+j] * 255.0;
                        }
                }
        }
        if (image) {
                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] >> 8;
+                               CV_IMAGE_ELEM(image, uchar, i, j) = img_buffer[i*width+j] * 255.0;
                                if (image_preview)
-                                       CV_IMAGE_ELEM(image_preview, uchar, i, j) = (img_buffer[(i*width+j)*3 + 1] / 2) >> 8;
+                                       CV_IMAGE_ELEM(image_preview, uchar, i, j) = (img_buffer[i*width+j] / 2) * 255.0;
                        }
                }
        }
        if (image_next) {
                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] >> 8;
+                               CV_IMAGE_ELEM(image_next, uchar, i, j) = img_next_buffer[i*width+j] * 255.0;
                        }
                }
        }
@@ -212,6 +209,12 @@ void *create_flow_maps(const unsigned short *img_prev_buffer, const unsigned sho
                }
        }
 
+#if 0
+#include<opencv/highgui.h>
+cvNamedWindow( "Display window", 0 );// Create a window for display.
+cvShowImage( "Display window", image );                   // Show our image inside it.
+#endif
+
        if (image)
                cvReleaseImage(&image);
        if (image_prev)
@@ -236,62 +239,76 @@ void *create_flow_maps(const unsigned short *img_prev_buffer, const unsigned sho
  * 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 short *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 short *img_prev_buffer = NULL, *img_next_buffer = NULL;
+       double *img_prev_buffer = NULL, *img_next_buffer = NULL, *img_buffer;
        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;
        unsigned char c;
        double r, g, b;
-       int w, h, rc;
+       int w, h;
        int i, j;
+       unsigned short *img;
 
 #if 0
        cvInitMatHeader(&kernel, 3, 3, CV_64FC1, vals, 0);
 #endif
 
 //printf("%s %s\n", filename_prev, filename_next);
+
+       /* convert current image to double */
+       img_buffer = (double *)malloc(width*height*3*sizeof(double));
+       if (!img_buffer) {
+               printf("%s:failed to allocate memory\n", __func__);
+               return;
+       }
+       img2array_short(_img_buffer, width, height, img_buffer, width, height);
+       rgb2yuv(img_buffer, img_buffer, width, height);
+
        /* read previous image */
        if (filename_prev) {
-               rc = load_img(-1, &img_prev_buffer, &w, &h, filename_prev, 0);
-               if (rc == 0) {
-                       if (w != width || h != height) {
-                               rc = -1;
-                               free(img_prev_buffer);
-                               img_prev_buffer = NULL;
+               img = load_img(&w, &h, filename_prev, 0);
+               if (img) {
+                       if (w == width && h == height) {
+                               img_prev_buffer = (double *)malloc(w*h*3*sizeof(double));
+                               if (img_prev_buffer) {
+                                       img2array_short(img, w, h, img_prev_buffer, w, h);
+                                       rgb2yuv(img_prev_buffer, img_prev_buffer, width, height);
+                               }
                        }
+                       free(img);
                }
        }
                
        /* read next image */
        if (filename_next) {
-               rc = load_img(-1, &img_next_buffer, &w, &h, filename_next, 0);
-               if (rc == 0) {
-                       if (w != width || h != height) {
-                               rc = -1;
-                               free(img_next_buffer);
-                               img_next_buffer = NULL;
+               img = load_img(&w, &h, filename_next, 0);
+               if (img) {
+                       if (w == width && h == height) {
+                               img_next_buffer = (double *)malloc(w*h*3*sizeof(double));
+                               if (img_next_buffer) {
+                                       img2array_short(img, w, h, img_next_buffer, w, h);
+                                       rgb2yuv(img_next_buffer, img_next_buffer, width, height);
+                               }
                        }
+                       free(img);
                }
        }
 
        /* apply images to opencv image */
        size.width = width;
        size.height = height;
-       if (img_buffer) {
-               image_preview = cvCreateImage(size, IPL_DEPTH_8U, 1);
-       }
+       image_preview = cvCreateImage(size, IPL_DEPTH_8U, 1);
 
        flow_map_x_prev = (double *)malloc(sizeof(double)*width*height);
        flow_map_y_prev = (double *)malloc(sizeof(double)*width*height);
        flow_map_x_next = (double *)malloc(sizeof(double)*width*height);
        flow_map_y_next = (double *)malloc(sizeof(double)*width*height);
 
-       if (image_preview)
+       if (image_preview) {
                image_preview = create_flow_maps(img_prev_buffer, img_next_buffer, img_buffer, width, height, win_size, steps, flow_map_x_prev, flow_map_y_prev, flow_map_x_next, flow_map_y_next, image_preview);
 
-       if (img_buffer && image_preview) {
                /* paint vectors from image_preview to img_buffer */
                for (i = 0; i < height; i++) {
                        for (j = 0; j < width; j++) {
@@ -314,19 +331,21 @@ void create_flow_view(const char *filename_prev, const char *filename_next, unsi
                                                        flow_map_y_next[width * i + j] / uv_scale,
                                                        &r, &g, &b);
                                        } else {
-                                               r = (double)c / 255.0;
-                                               g = (double)c / 255.0;
-                                               b = (double)c / 255.0;
+                                               r = ((double)c) / 255.0;
+                                               g = ((double)c) / 255.0;
+                                               b = ((double)c) / 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;
+                               _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;
                        }
                }
        }
 
        /* free stuff */
+       if (img_buffer)
+               free(img_buffer);
        if (img_prev_buffer)
                free(img_prev_buffer);
        if (img_next_buffer)
index a144d1f..59be9eb 100644 (file)
@@ -4,6 +4,6 @@ void flow_default(void);
 void save_flow(const char *filename);
 int load_flow(const char *filename);
 
-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_maps(const double *img_prev_buffer, const double *img_next_buffer, const double *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 short *img_buffer, int width, int height, int win_size, int steps, int uv_scale);
diff --git a/src/ppm.c b/src/ppm.c
deleted file mode 100755 (executable)
index f5e6fbb..0000000
--- a/src/ppm.c
+++ /dev/null
@@ -1,294 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "ppm.h"
-
-#ifdef WITH_MAGICK
-#include <magick/api.h>
-
-int save_depth = 16;
-
-/* load given image to memory. return memory pointer, witdth and height
- * if offset is given, no memory is allocated */
-int load_img(int offset, unsigned short **buffer, int *width, int *height,
-       const char *filename, int index)
-{
-       int rc = -1;
-       Image *image = NULL;
-       ImageInfo *imageinfo = NULL;
-       ExceptionInfo exception;
-
-//     MagickCoreGenesis(NULL,MagickFalse);
-       InitializeMagick(NULL);
-       imageinfo = CloneImageInfo(0);
-       GetExceptionInfo(&exception);
-
-       sprintf(imageinfo->filename, filename, index);
-
-       image = ReadImage(imageinfo, &exception);
-       if (!image) {
-//             printf("failed to read image '%s' via *magick\n", filename);
-               goto exit;
-       }
-       *width = image->columns;
-       *height = image->rows;
-
-       if (offset < 0) {
-               *buffer = (unsigned short *)malloc((*width) * (*height) * 3 * sizeof(unsigned short));
-               if (!*buffer) {
-                       printf("failed to allocate image data\n");
-                       goto exit;
-               }
-               offset = 0;
-       }
-//     ExportImagePixels(image, 0, 0, *width, *height, "RGB", CharPixel, *buffer, NULL);
-       DispatchImage(image, 0, 0, *width, *height, "RGB", ShortPixel, *buffer, NULL);
-
-       rc = 0;
-
-exit:
-       if (image)
-               DestroyImage(image);
-
-       if (imageinfo)
-               DestroyImageInfo(imageinfo);
-
-//     MagickCoreTerminus();
-       DestroyMagick();
-
-       return rc;
-}
-
-/* save given image */
-int save_img(unsigned short *buffer, int width, int height, const char *filename,
-       int index)
-{
-       int rc = -1;
-       Image *image = NULL;
-       ImageInfo *imageinfo = NULL;
-       ExceptionInfo exception;
-
-//     MagickCoreGenesis(NULL,MagickFalse);
-       InitializeMagick(NULL);
-       imageinfo = CloneImageInfo(0);
-       GetExceptionInfo(&exception);
-
-       imageinfo->quality = 100;
-
-       image=ConstituteImage(width, height, "RGB", ShortPixel, buffer, &exception);
-       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");
-               goto exit;
-       }
-
-       rc = 0;
-
-exit:
-       if (image)
-               DestroyImage(image);
-
-       if (imageinfo)
-               DestroyImageInfo(imageinfo);
-
-//     MagickCoreTerminus();
-       DestroyMagick();
-
-       return rc;
-}
-#else
-
-/* 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 short **buffer, int *width, int *height,
-       const char *filename, int index)
-{
-       FILE *fp;
-       char line[256];
-       int words, i;
-
-       sprintf(line, filename, index);
-//     printf("reading image: %s\n", line);
-       fp = fopen(line, "r");
-       if (!fp) {
-//             printf("failed to read ppm image '%s'\n", filename);
-               return -1;
-       }
-again1:
-       if (!fgets(line, sizeof(line), fp)) {
-               printf("failed to read image depth\n");
-               fclose(fp);
-               return -1;
-       }
-       line[sizeof(line)-1] = '\0';
-       if (line[0]) line[strlen(line)-1] = '\0';
-       if (line[0] == '#')
-               goto again1;
-       if (!!strcmp(line, "P6")) {
-               printf("expecting image depth 'P6'\n");
-               fclose(fp);
-               return -1;
-       }
-again2:
-       if (!fgets(line, sizeof(line), fp)) {
-               printf("failed to read image size\n");
-               fclose(fp);
-               return -1;
-       }
-       line[sizeof(line)-1] = '\0';
-       if (line[0]) line[strlen(line)-1] = '\0';
-       if (line[0] == '#')
-               goto again2;
-       sscanf(line, "%d %d", width, height);
-//     printf("Image size: w=%d h=%d\n", *width, *height);
-again3:
-       if (!fgets(line, sizeof(line), fp)) {
-               printf("failed to read line '255' or '65535'\n");
-               fclose(fp);
-               return -1;
-       }
-       line[sizeof(line)-1] = '\0';
-       if (line[0]) line[strlen(line)-1] = '\0';
-       if (line[0] == '#')
-               goto again3;
-       if (!strcmp(line, "255")) {
-               words = 1;
-       } else
-       if (!strcmp(line, "65535")) {
-               words = 2;
-       } else {
-               printf("expecting line '255' or '65535'\n");
-               fclose(fp);
-               return -1;
-       }
-       if (offset < 0) {
-               *buffer = (unsigned short *)malloc((*width) * (*height) * 3 * words * sizeof(unsigned short));
-               if (!*buffer) {
-                       printf("failed to allocate image data\n");
-                       fclose(fp);
-                       return -1;
-               }
-               offset = 0;
-       }
-       if (fread((*buffer) + offset, (*width) * (*height) * 3 * words, 1, fp) != 1) {
-               printf("failed to read image data\n");
-               free(*buffer);
-               fclose(fp);
-               return -1;
-       }
-
-       /* 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);
-
-       return 0;
-}
-
-/* save given image */
-int save_img(unsigned short *buffer, int width, int height, const char *filename,
-       int index)
-{
-       FILE *fp;
-       int rc;
-       char line[256];
-
-       sprintf(line, filename, index);
-//     printf("writing image: %s\n", line);
-       fp = fopen(line, "w");
-       if (!fp) {
-               printf("failed to write image\n");
-               return -1;
-       }
-       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;
-}
-#endif
-
-/* convert an image to a three dimensional array of double
- * the size is: width, height, 3
- */
-void img2array(unsigned short *img, int iw, int ih, double *array, int aw,
-       int ah)
-{
-       int x, y;
-       int plane = aw * ah;
-       double r, g, b;
-
-       for (y = 0; y < ih; y++) {
-               for (x = 0; x < iw; x++) {
-                       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;
-               }
-       }
-}
-
-/* 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 short *img, int iw,
-       int ih)
-{
-       int x, y, c;
-       int plane = aw * ah;
-       double r, g, b;
-
-       for (y = 0; y < ih; y++) {
-               for (x = 0; x < iw; x++) {
-                       r = array[x+aw*y];
-                       g = array[x+aw*y+plane];
-                       b = array[x+aw*y+plane+plane];
-                       c = (r * 65535.0F + 0.5F);
-                       if (c < 0)
-                               c = 0;
-                       else if (c > 65535)
-                               c = 65535;
-                       img[(x+iw*y)*3] = c;
-                       c = (g * 65535.0F + 0.5F);
-                       if (c < 0)
-                               c = 0;
-                       else if (c > 65535)
-                               c = 65535;
-                       img[(x+iw*y)*3+1] = c;
-                       c = (b * 65535.0F + 0.5F);
-                       if (c < 0)
-                               c = 0;
-                       else if (c > 65535)
-                               c = 65535;
-                       img[(x+iw*y)*3+2] = c;
-               }
-       }
-}
-
-
diff --git a/src/ppm.h b/src/ppm.h
deleted file mode 100644 (file)
index 968b70c..0000000
--- a/src/ppm.h
+++ /dev/null
@@ -1,6 +0,0 @@
-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);
-
diff --git a/src/process.c b/src/process.c
new file mode 100644 (file)
index 0000000..a412dc2
--- /dev/null
@@ -0,0 +1,270 @@
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <math.h>
+#include <time.h>
+#include "../lib/darray.h"
+#include "yuv.h"
+#include "mark.h"
+#include "process.h"
+
+/*
+ * create image array and marked array
+ */
+int alloc_I_arrays(darray_t **I, darray_t **mI, int w, int h, int k, int *features, char **feat_names, int change_alpha, int change_bc)
+{
+       int dims[4];
+
+       dims[0] = w; dims[1] = h; dims[2] = k;
+       *mI = darrayCreate(3, dims);
+       if (!*mI) {
+               printf("%s:failed to create mark array\n", __func__);
+               goto exit;
+       }
+       *features = 2; /* u and v */
+       feat_names[0] = "u";
+       feat_names[1] = "v";
+       if (change_alpha) {
+               *features += 2;
+               feat_names[2] = "alpha";
+               feat_names[3] = "y-removal";
+       }
+       if (change_bc) {
+               *features += 2;
+               if (change_alpha) {
+                       feat_names[4] = "brightness";
+                       feat_names[5] = "contrast";
+               } else {
+                       feat_names[2] = "brightness";
+                       feat_names[3] = "contrast";
+               }
+       }
+       dims[0] = w; dims[1] = h; dims[2] = *features + 1; dims[3] = k;
+       *I = darrayCreate(4, dims);
+       if (!*I) {
+               printf("%s:failed to create image array\n", __func__);
+               goto exit;
+       }
+
+       return 0;
+
+exit:
+       if (*I)
+               darrayDestroy(*I);
+       if (*mI)
+               darrayDestroy(*mI);
+
+       return -1;
+}
+
+/*
+ * set pointers to image/mark arrays
+ */
+void set_I_ptr(darray_t *I, darray_t *mI, int w, int h, int z, int features, int change_alpha, int change_bc, double **ptr_y, double **ptr_u, double **ptr_v, double **ptr_a, double **ptr_r, double **ptr_b, double **ptr_c, double **ptr_m)
+{
+       *ptr_y = darrayGetPr(I) + w*h*(features+1)*z;
+       *ptr_u = *ptr_y + w*h;
+       *ptr_v = *ptr_u + w*h;
+       if (change_alpha) {
+               *ptr_a = *ptr_v + w*h;
+               *ptr_r = *ptr_a + w*h;
+       }
+       if (change_bc) {
+               if (change_alpha)
+                       *ptr_b = *ptr_r + w*h;
+               else
+                       *ptr_b = *ptr_v + w*h;
+               *ptr_c = *ptr_b + w*h;
+       }
+       *ptr_m = darrayGetPr(mI) + w*h*z;
+}
+
+/*
+ * use cI, gI and mI to prepare image array
+ */
+void prepare_arrays(int w, int h, int change_alpha, int change_bc, unsigned char *mark_buffer, double *ptr_gI, double *ptr_cI, double *ptr_y, double *ptr_u, double *ptr_v, double *ptr_a, double *ptr_r, double *ptr_b, double *ptr_c, double *ptr_m, enum test test)
+{
+       int x, y;
+
+       if (test != BC_ONLY) {
+               unsigned char c;
+               // generate I image: use luminance from original image and chrominance from original or marked image
+               /* use original y component */
+               memcpy(ptr_y, ptr_gI, w*h*sizeof(double));
+               /* apply new uv components */
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               c = mark_buffer[y*w+x];
+                               if (c == 0) {
+                                       ptr_u[w*y+x] = ptr_gI[w*h + w*y+x];
+                                       ptr_v[w*y+x] = ptr_gI[w*h*2 + w*y+x];
+                               } else {
+                                       ptr_u[w*y+x] = ptr_cI[w*h + w*y+x];
+                                       ptr_v[w*y+x] = ptr_cI[w*h*2 + w*y+x];
+                               }
+                       }
+               }
+       } else {
+               /* use grey image as result if BC_ONLY test is selected */
+               memcpy(ptr_y, ptr_gI, w*h*3*sizeof(double));
+       }
+
+       if (change_alpha) {
+               double alpha;
+               unsigned char c;
+               /* apply alpha from marked pixles to alpha component of grey image
+                * also create a removal image to remove luminance from alpha after colorization
+                * also remove color from u and v marks now */
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               c = mark_buffer[y*w+x];
+                               if (c == 0) {
+                                       ptr_a[y*w+x] = 0.5;
+                                       ptr_r[y*w+x] = 0.0;
+                               } else {
+                                       alpha = mark_palette[c-1].alpha;
+                                       /* opaqueness */
+                                       ptr_a[y*w+x] = alpha;
+                                       /* keep luminance according to transparency */
+                                       ptr_r[y*w+x] = (1.0 - alpha) * ptr_y[y*w+x];
+                                       /* remove color from u and v, according to transparency  */
+                                       ptr_u[y*w+x] *= alpha;
+                                       ptr_v[y*w+x] *= alpha;
+                               }
+                       }
+               }
+       }
+
+       if (change_bc) {
+               unsigned char c;
+               /* apply brightness and contrast from makred pixles to bc components of grey image */
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               /* use unchanged brightness and contrast on index 0 */
+                               c = mark_buffer[y*w+x];
+                               if (c == 0) {
+                                       ptr_b[y*w+x] = 0.0;
+                                       ptr_c[y*w+x] = 0.1;
+                               } else {
+                                       ptr_b[y*w+x] = mark_palette[c-1].bright / 10.0;
+                                       ptr_c[y*w+x] = mark_palette[c-1].contrast / 10.0;
+                               }
+                       }
+               }
+       }
+}
+
+void postpare_arrays(int w, int h, int change_alpha, int change_bc, double *ptr_y, double *ptr_u, double *ptr_v, double *ptr_a, double *ptr_r, double *ptr_b, double *ptr_c, double *ptr_m, enum test test)
+{
+       int x, y;
+
+       /* if we have a change, we remove y from transparent pixles, according to transparency
+        * also we normalize the remaining pixles according to transparency
+        *
+        * y = y - r / alpha  (r = removal image)
+        * u = u / alpha
+        * v = v / alpha
+        */
+       if (change_alpha && test != REMOVAL_IMAGE) {
+               double alpha, lum;
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               alpha = ptr_a[w*y+x];
+                               /* if transparent, the result is undefined */
+                               if (alpha < 0.0001)
+                                       continue;
+                               lum = ptr_y[w*y+x] - ptr_r[w*y+x];
+                               /* if negative, assume black pixle */
+                               if (lum < 0)
+                                       lum = 0;
+                               /* normalize yuv */
+                               ptr_y[w*y+x] = lum / alpha;
+                               ptr_u[w*y+x] /= alpha;
+                               ptr_v[w*y+x] /= alpha;
+                       }
+               }
+       }
+
+       /* if we have a change, we apply brightness+contrast from image array */
+       if (change_bc) {
+               double lum;
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               /* apply contrast */
+                               lum = ptr_y[w*y+x];
+                               lum = (lum - 0.5) * ptr_c[w*y+x] * 10.0 + 0.5;
+                               /* apply brightness */
+                               lum += ptr_b[w * y + x] * 10.0;
+                               if (lum < 0)
+                                       lum = 0;
+                               if (lum > 1)
+                                       lum = 1;
+                               ptr_y[w*y+x] = lum;
+#if 0
+#warning TEST: show brightness and contrast change as uv vectors on a grey array */
+ptr_y[w*y+x] = 0.5;
+ptr_u[w*y+x] = ptr_b[w*y+x] * 10;
+ptr_v[w*y+x] = ptr_c[w*y+x] * 10 - 1;
+#endif
+                       }
+               }
+       }
+
+       if (test == MASK) {
+               /* apply maked mask as image */
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               ptr_y[w*y+x] = ptr_m[w*y+x];
+                               ptr_u[w*y+x] = 0;
+                               ptr_v[w*y+x] = 0;
+                       }
+               }
+       }
+
+       if (test == MASK_COLOR) {
+               /* apply maked mask on grey image */
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               /* darken unmarked areas, make maked areas with uniformed brightness */
+                               if (ptr_m[w*y+x] < 0.5)
+                                       ptr_y[w*y+x] = ptr_y[w*y+x] / 4;
+                               else
+                                       ptr_y[w*y+x] = 0.5;
+                       }
+               }
+       }
+
+       if (test == BC_IMAGE) {
+               /* apply bc image as result image */
+               /* use uniformed brightness as y component */
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++) {
+                               ptr_y[w*y+x] = 0.5;
+                       }
+               }
+               /* display B and C as U and V */
+               if (change_bc) {
+                       memcpy(ptr_u, ptr_b, w*h*sizeof(double));
+                       memcpy(ptr_v, ptr_c, w*h*sizeof(double));
+               } else {
+                       memset(ptr_u, 0, w*h*sizeof(double));
+                       memset(ptr_v, 0, w*h*sizeof(double));
+               }
+       }
+
+       if (test == ALPHA) {
+               /* apply alpha image as result y component only */
+               memcpy(ptr_y, ptr_a, w*h*sizeof(double));
+               memset(ptr_u, 0, w*h*sizeof(double));
+               memset(ptr_v, 0, w*h*sizeof(double));
+       }
+
+       if (test == REMOVAL_IMAGE) {
+               /* apply removal image as result y component */
+               memcpy(ptr_y, ptr_r, w*h*sizeof(double));
+       }
+}
+
diff --git a/src/process.h b/src/process.h
new file mode 100644 (file)
index 0000000..5a160e0
--- /dev/null
@@ -0,0 +1,20 @@
+
+enum test {
+       NO_TEST = 0,
+       FLOW_NEXT,
+       FLOW_PREV,
+       MARKED,
+       MASK,
+       MASK_COLOR,
+       BC_ONLY,
+       BC_IMAGE,
+       ALPHA,
+       NO_ALPHA,
+       REMOVAL_IMAGE,
+};
+
+int alloc_I_arrays(darray_t **I, darray_t **mI, int w, int h, int k, int *features, char **feat_names, int change_alpha, int change_bc);
+void set_I_ptr(darray_t *I, darray_t *mI, int w, int h, int z, int features, int change_alpha, int change_bc, double **ptr_y, double **ptr_u, double **ptr_v, double **ptr_a, double **ptr_r, double **ptr_b, double **ptr_c, double **ptr_m);
+void prepare_arrays(int w, int h, int change_alpha, int change_bc, unsigned char *mark_buffer, double *ptr_gI, double *ptr_cI, double *ptr_y, double *ptr_u, double *ptr_v, double *ptr_a, double *ptr_r, double *ptr_b, double *ptr_c, double *ptr_m, enum test test);
+void postpare_arrays(int w, int h, int change_alpha, int change_bc, double *ptr_y, double *ptr_u, double *ptr_v, double *ptr_a, double *ptr_r, double *ptr_b, double *ptr_c, double *ptr_m, enum test test);
+
index 59f78fd..1aad6c7 100644 (file)
@@ -10,7 +10,7 @@ bin_PROGRAMS = \
        fields
 
 fields_SOURCES = \
-       ../src/ppm.c \
+       ../src/img.c \
        fields.c
 fields_LDADD = \
        $(COMMON_LA) $(GRAPHICSMAGICK_LIBS) $(IMAGEMAGICK_LIBS)
index ca49e65..8649a65 100644 (file)
@@ -2,7 +2,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include "../src/ppm.h"
+#include "../src/img.h"
 
 /* split interlaced image into two fields */
 static void split_image(const unsigned short *source, unsigned short *dest1,
@@ -72,16 +72,17 @@ usage:
 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[_arg+1], frame++))
+               frame_img = load_img(&width, &height, argv[_arg+1], frame++);
+               if (!frame_img)
                        goto out;
                if (!(field1_img = malloc(width * height/2 * 3 * sizeof(unsigned short))))
                        goto out;
                if (!(field2_img = malloc(width * height/2 * 3 * sizeof(unsigned short))))
                        goto out;
                split_image(frame_img, field1_img, field2_img, width, height);
-               if (save_img(field1_img, width, height/2, argv[_arg+2], field++))
+               if (save_img(field1_img, width, height/2, 0, argv[_arg+2], field++))
                        goto out;
-               if (save_img(field2_img, width, height/2, argv[_arg+2], field++))
+               if (save_img(field2_img, width, height/2, 0, argv[_arg+2], field++))
                        goto out;
                free(frame_img);
                free(field1_img);
@@ -89,14 +90,16 @@ next_frame:
                goto next_frame;
        }
        if (mode == MODE_FIELD_2_FRAME) {
-               if (load_img(-1, &field1_img, &width, &height, argv[_arg+1], field++))
+               field1_img = load_img(&width, &height, argv[_arg+1], field++);
+               if (!field1_img)
                        goto out;
-               if (load_img(-1, &field2_img, &width, &height, argv[_arg+1], field++))
+               field2_img = load_img(&width, &height, argv[_arg+1], field++);
+               if (!field2_img)
                        goto out;
                if (!(frame_img = malloc(width * height*2 * 3 * sizeof(unsigned short))))
                        goto out;
                join_image(field1_img, field2_img, frame_img, width, height*2);
-               if (save_img(frame_img, width, height*2, argv[_arg+2], frame++))
+               if (save_img(frame_img, width, height*2, 0, argv[_arg+2], frame++))
                        goto out;
                free(field1_img);
                free(field2_img);