#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 */
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;
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);
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;
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);
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++) {
}
}
+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];
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;
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;
}
}
}
}
+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;
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)
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;
}
}