Add option to GUI to load rendered images from different prefix
[colorize.git] / gui / image.c
index 70f5cb7..6a971ef 100644 (file)
@@ -4,12 +4,13 @@
 #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"
 #include "palette.h"
 #include "timeline.h"
+#include "colorize.h"
 #include "../src/dir_seperator.h"
 
 /* currently loaded image */
@@ -18,7 +19,7 @@ GdkPixbuf *img_pixbuf = NULL;
 int img_width, img_height;
 int copy_width, copy_height;
 char img_name[256];
-unsigned char *img_grey_buffer = NULL;
+unsigned short *img_grey_buffer = NULL, *img_preview_buffer = NULL;
 unsigned char *img_mark_buffer = NULL, *img_mark_buffer_undo[UNDO_MAX], *img_mark_buffer_copy;
 int button_down_x_undo[UNDO_MAX], button_down_y_undo[UNDO_MAX];
 int undo_current, undo_num;
@@ -27,43 +28,27 @@ int anything_modified;
 extern int button_down_x, button_down_y;
 
 /* load image and create pixbuf */
-void create_image(const char *filename)
+void create_image(const char *filename, int resize)
 {
-       int rc;
-       static char imgfile[256];
-
        destroy_image();
 
        anything_modified = 0;
 
        strcpy(img_name, filename);
-       if (rendered) {
-               const char *p, *q;
-               p = filename;
-               while((q = strchr(p, DIR_SEPERATOR)))
-               p = q + 1;
-               strcpy(imgfile, filename);
-               imgfile[p - filename] = '\0';
-               strcat(imgfile, "colorized_");
-               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 = NULL;
-               if (!rendered)
-                       printerror("Failed to load grey image '%s'", imgfile);
-               else {
-                       img_width = 16;
-                       img_height = 16;
-                       goto no_mark;
-               }
+       img_grey_buffer = load_img(&img_width, &img_height, filename, 0);
+       if (!img_grey_buffer) {
+               printerror("Failed to load grey image '%s'", filename);
                return;
        }
+       if (preview)
+               create_preview();
+       else if (rendered)
+               create_rendered(filename);
        img_mark_buffer = malloc(img_width*img_height);
        if (!img_mark_buffer) {
                free(img_grey_buffer);
                img_grey_buffer = NULL;
+               destroy_preview();
                return;
        }
        memset(img_mark_buffer, 0, img_width*img_height);
@@ -76,13 +61,124 @@ void create_image(const char *filename)
                        frame_list[timeline_selected].marked = 0;
        }
 
-no_mark:
        /* create pixbuf */
-       create_or_reset_pixbuf();
+       create_or_reset_pixbuf(resize);
+}
+
+void create_preview()
+{
+       size_t size = img_width*img_height*3*sizeof(*img_preview_buffer);
+
+       destroy_preview();
+
+       /* no grey image, so no preview */
+       if (!img_grey_buffer) {
+               return;
+       }
+
+       img_preview_buffer = malloc(size);
+       if (!img_preview_buffer) {
+               return;
+       }
+
+       memcpy(img_preview_buffer, img_grey_buffer, size);
+
+       colorize_preview_alloc();
+}
+
+void create_rendered(const char *filename)
+{
+       static char imgfile[256];
+       const char *p, *q;
+       int width, height;
+
+       destroy_preview();
+
+       /* no grey image, so no preview */
+       if (!img_grey_buffer) {
+               return;
+       }
+
+       p = filename;
+       while((q = strchr(p, DIR_SEPERATOR)))
+               p = q + 1;
+       if (output_prefix[0] == '\0') {
+               strcpy(imgfile, filename);
+               imgfile[p - filename] = '\0';
+               strcat(imgfile, "colorized_");
+       } else {
+               strcpy(imgfile, output_prefix);
+       }
+       strcat(imgfile, p);
+
+       img_preview_buffer = load_img(&width, &height, imgfile, 0);
+       if (!img_preview_buffer) {
+               printerror("Failed to load rendered image '%s'", imgfile);
+               return;
+       }
+       if (width != img_width || height != img_height) {
+               printerror("Failed to load: Rendered image '%s' has different size", imgfile);
+               destroy_preview();
+               return;
+       }
 }
 
-void create_or_reset_pixbuf(void)
+void create_or_reset_pixbuf(int resize)
 {
+       int w, h, dw = 0, dh = 0;
+       GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(main_window));
+       GdkRectangle max;
+
+       if (resize && screen) {
+               /* process GTK window event to have correct size */
+               while (gtk_events_pending())
+                       gtk_main_iteration();
+
+               /* calculate the maximum windows size, so that the border will not exceed the screen size */
+               gdk_window_get_frame_extents(gtk_widget_get_window(main_window), &max);
+               max.width -= main_window->allocation.width;
+               max.height -= main_window->allocation.height;
+               if (max.width < 0)
+                       max.width = 0;
+               if (max.height < 0)
+                       max.height = 0;
+               max.width = gdk_screen_get_width(screen)-max.width;
+               max.height = gdk_screen_get_height(screen)-max.height;
+
+try_smaller:
+               w = img_scroll->allocation.width-25;
+               h = img_scroll->allocation.height-25;
+               if (w < img_width*img_scale_x/16) {
+                       w = main_window->allocation.width - w + img_width*img_scale_x/16;
+                       if (w > max.width) {
+                               if (img_scale_x > 4) {
+                                       int aspect = img_scale_y / img_scale_x;
+                                       img_scale_x -= 4;
+                                       img_scale_y = img_scale_x * aspect;
+                                       goto try_smaller;
+                               }
+                               w = max.width;
+                       }
+                       dw = w - main_window->allocation.width;
+               }
+               if (h < img_height*img_scale_y/16) {
+                       h = main_window->allocation.height - h + img_height*img_scale_y/16;
+                       if (h > max.height) {
+                               if (img_scale_x > 4) {
+                                       int aspect = img_scale_y / img_scale_x;
+                                       img_scale_x -= 4;
+                                       img_scale_y = img_scale_x * aspect;
+                                       goto try_smaller;
+                               }
+                               h = max.height;
+                       }
+                       dh = h - main_window->allocation.height;
+               }
+//             printf("%d %d\n", gdk_screen_get_width(screen), gdk_screen_get_height(screen));
+               if (dw || dh)
+                       gtk_window_resize(GTK_WINDOW(main_window), main_window->allocation.width+dw, main_window->allocation.height+dh);
+       }
+
        if (img_pixbuf) {
                g_object_unref(img_pixbuf);
                img_pixbuf = NULL;
@@ -90,7 +186,6 @@ void create_or_reset_pixbuf(void)
        img_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, img_width*img_scale_x/16, img_height*img_scale_y/16);
 
        gtk_drawing_area_size(GTK_DRAWING_AREA(img_drawing_area), img_width*img_scale_x/16, img_height*img_scale_y/16);
-//     gtk_widget_set_size_request(drawing_area, img_width, img_height);
 
        /* label */
        timeline_show_name(timeline_selected);
@@ -109,6 +204,7 @@ void destroy_image(void)
 
        free(img_grey_buffer);
        img_grey_buffer = NULL;
+       destroy_preview();
        free(img_mark_buffer);
        img_mark_buffer = NULL;
        for (i = 0; i < UNDO_MAX; i++) {
@@ -119,19 +215,26 @@ void destroy_image(void)
        }
 }
 
+void destroy_preview(void)
+{
+       colorize_preview_free();
+       free(img_preview_buffer);
+       img_preview_buffer = NULL;
+}
+
 /* draw (area) of pixbuf */
 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;
-       int _c, preview_asis = 0;
+       double _r, _g, _b, pat, alpha;
+       int cr, cg, cb;
 
        if (w < 0)
                w = window_width;
        if (h < 0)
-               h = window_width;
+               h = window_height;
 
        guchar *data;
        unsigned char compose[w*3];
@@ -213,57 +316,40 @@ void draw_image(int x, int y, int w, int h)
        y -= y_offset;
 
        if (img_grey_buffer) {
-               if (preview) {
-                       rgb2yuv_pixle(mark_palette[mark_selected].r / 255.0F, mark_palette[mark_selected].g / 255.0F, mark_palette[mark_selected].b / 255.0F, &_y, &u_palette, &v_palette);
-                       /* check for white color (no change) */
-                       if (mark_palette[mark_selected].r == 255 && mark_palette[mark_selected].g == 255 && mark_palette[mark_selected].r == 255)
-                               preview_asis = 1;
-               }
                /* compose image (segment) line by line */
                for (i = 0; i < h; i++) {
                        for (j = 0; j < w; j++) {
-                               if (preview && !rendered && !flowview) {
-                                       /* apply selected color from palette to all pixles */
-                                       _r = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] / 255.0F;
-                                       _g = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] / 255.0F;
-                                       _b = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] / 255.0F;
-                                       rgb2yuv_pixle(_r, _g, _b, &_y, &_u, &_v);
-                                       _y = (_y - 0.5) * mark_palette[mark_selected].contrast + 0.5;
-                                       _y += mark_palette[mark_selected].bright;
-                                       if (_y < 0)
-                                               _y = 0;
-                                       if (_y > 1)
-                                               _y = 1;
-                                       if (preview_asis)
-                                               yuv2rgb_pixle(_y, _u, _v, &_r, &_g, &_b);
-                                       else
-                                               yuv2rgb_pixle(_y, u_palette, v_palette, &_r, &_g, &_b);
-                                       _c = _r * 255.0F;
-                                       if (_c < 0)
-                                               _c = 0;
-                                       else if (_c > 255)
-                                               _c = 255;
-                                       compose[j*3] = _c;
-                                               _c = _g * 255.0F;
-                                       if (_c < 0)
-                                               _c = 0;
-                                       else if (_c > 255)
-                                               _c = 255;
-                                       compose[j*3+1] = _c;
-                                               _c = _b * 255.0F;
-                                       if (_c < 0)
-                                               _c = 0;
-                                       else if (_c > 255)
-                                               _c = 255;
-                                       compose[j*3+2] = _c;
-
+                               if (img_preview_buffer) {
+                                       /* show preview buffer */
+                                       compose[j*3] = img_preview_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] >> 8;
+                                       compose[j*3+1] = img_preview_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] >> 8;
+                                       compose[j*3+2] = img_preview_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] >> 8;
                                } else {
-                                       compose[j*3] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3];
-                                       compose[j*3+1] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1];
-                                       compose[j*3+2] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2];
+                                       /* show grey buffer */
+                                       compose[j*3] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] >> 8;
+                                       compose[j*3+1] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] >> 8;
+                                       compose[j*3+2] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] >> 8;
                                }
                                c = img_mark_buffer[(j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y)];
-                               if (c > 0 && !flowview && !(rendered && preview)) {
+                               if (c > 0 && !flowview) {
+                                       if (mark) {
+                                               cr = mark_palette[c-1].r;
+                                               cg = mark_palette[c-1].g;
+                                               cb = mark_palette[c-1].b;
+                                               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;
+                                       }
                                        if (highlight) {
                                                if (c-1 == mark_selected) {
                                                        compose[j*3] = 255;
@@ -274,10 +360,6 @@ void draw_image(int x, int y, int w, int h)
                                                        compose[j*3+1] = 0;
                                                        compose[j*3+2] = 128;
                                                }
-                                       } else {
-                                               compose[j*3] = mark_palette[c-1].r;
-                                               compose[j*3+1] = mark_palette[c-1].g;
-                                               compose[j*3+2] = mark_palette[c-1].b;
                                        }
                                }
                        }
@@ -292,12 +374,69 @@ void draw_image(int x, int y, int w, int h)
 
 }
 
+static const char *brushs[] = {
+       NULL,
+       "#",
+       " # "
+       "###"
+       " # ",
+       " ### "
+       "#####"
+       "#####"
+       "#####"
+       " ### ",
+       NULL,
+       "  #####  "
+       " ####### "
+       "#########"
+       "#########"
+       "#########"
+       "#########"
+       "#########"
+       " ####### "
+       "  #####  ",
+       "    ###    "
+       "  #######  "
+       " ######### "
+       " ######### "
+       "###########"
+       "###########"
+       "###########"
+       " ######### "
+       " ######### "
+       "  #######  "
+       "    ###    ",
+       NULL,
+       NULL,
+       NULL,
+       "      #######      "
+       "    ###########    "
+       "   #############   "
+       "  ###############  "
+       " ################# "
+       " ################# "
+       "###################"
+       "###################"
+       "###################"
+       "###################"
+       "###################"
+       "###################"
+       "###################"
+       " ################# "
+       " ################# "
+       "  ###############  "
+       "   #############   "
+       "    ###########    "
+       "      #######      ",
+};
+
 /* plot brush on mark buffer */
 void paint_brush(int x, int y, int size, int paint)
 {
        GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
        int window_width, window_height;
        gdk_drawable_get_size (draw, &window_width, &window_height);
+       const char *mask;
 
        /* we need to calculate an offset, since the drawing area is now larger */
        x -= (window_width - img_width*img_scale_x/16) / 2;
@@ -313,20 +452,25 @@ void paint_brush(int x, int y, int size, int paint)
        int x2 = x + size - 1;
        int y1 = y - size + 1;
        int y2 = y + size - 1;
-       int i, j;
+       int clipx = 0, clipy = 0, stride;
+       int i, j, jj;
 
        if (x1 >= img_width)
                return;
-       if (x1 < 0)
+       if (x1 < 0) {
+               clipx = -x1;
                x1 = 0;
+       }
        if (x2 >= img_width)
                x2 = img_width - 1;
        if (x2 < 0)
                return;
        if (y1 >= img_height)
                return;
-       if (y1 < 0)
+       if (y1 < 0) {
+               clipy = -y1;
                y1 = 0;
+       }
        if (y2 >= img_height)
                y2 = img_height - 1;
        if (y2 < 0)
@@ -336,10 +480,14 @@ void paint_brush(int x, int y, int size, int paint)
        if (paint)
                paint = mark_selected + 1;
 
+       stride = size + size - 1;
+       mask = brushs[size] + stride * clipy + clipx;
        for (i = y1; i <= y2; i++) {
-               for (j = x1; j <= x2; j++) {
-                       img_mark_buffer[j+img_width*i] = paint;
+               for (j = x1, jj = 0; j <= x2; j++, jj++) {
+                       if (mask[jj] == '#')
+                               img_mark_buffer[j+img_width*i] = paint;
                }
+               mask += stride;
        }
 }