7 #include "../src/ppm.h"
8 #include "../src/mark.h"
9 #include "../src/yuv.h"
13 #include "../src/dir_seperator.h"
15 /* currently loaded image */
17 GdkPixbuf *img_pixbuf = NULL;
18 int img_width, img_height;
19 int copy_width, copy_height;
21 unsigned char *img_grey_buffer = NULL;
22 unsigned char *img_mark_buffer = NULL, *img_mark_buffer_undo[UNDO_MAX], *img_mark_buffer_copy;
23 int button_down_x_undo[UNDO_MAX], button_down_y_undo[UNDO_MAX];
24 int undo_current, undo_num;
25 int img_scale_x = 16, img_scale_y = 16;
26 int anything_modified;
27 extern int button_down_x, button_down_y;
29 /* load image and create pixbuf */
30 void create_image(const char *filename)
33 static char imgfile[256];
37 anything_modified = 0;
39 strcpy(img_name, filename);
43 while((q = strchr(p, DIR_SEPERATOR)))
45 strcpy(imgfile, filename);
46 imgfile[p - filename] = '\0';
47 strcat(imgfile, "colorized_");
50 strcpy(imgfile, filename);
51 rc = load_img(-1, &img_grey_buffer, &img_width, &img_height, imgfile, 0);
53 img_grey_buffer = NULL;
55 printerror("Failed to load grey image '%s'", imgfile);
63 img_mark_buffer = malloc(img_width*img_height);
64 if (!img_mark_buffer) {
65 free(img_grey_buffer);
66 img_grey_buffer = NULL;
69 memset(img_mark_buffer, 0, img_width*img_height);
70 undo_current = undo_num = 0;
71 memset(img_mark_buffer_undo, 0, sizeof(img_mark_buffer_undo));
73 if (load_marked(img_mark_buffer, img_width, img_height, frame_list[timeline_selected].filename) == 0)
74 frame_list[timeline_selected].marked = 1;
76 frame_list[timeline_selected].marked = 0;
81 create_or_reset_pixbuf();
84 void create_or_reset_pixbuf(void)
87 g_object_unref(img_pixbuf);
90 img_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, img_width*img_scale_x/16, img_height*img_scale_y/16);
92 gtk_drawing_area_size(GTK_DRAWING_AREA(img_drawing_area), img_width*img_scale_x/16, img_height*img_scale_y/16);
93 // gtk_widget_set_size_request(drawing_area, img_width, img_height);
96 timeline_show_name(timeline_selected);
100 void destroy_image(void)
107 g_object_unref(img_pixbuf);
110 free(img_grey_buffer);
111 img_grey_buffer = NULL;
112 free(img_mark_buffer);
113 img_mark_buffer = NULL;
114 for (i = 0; i < UNDO_MAX; i++) {
115 if (img_mark_buffer_undo[i]) {
116 free(img_mark_buffer_undo[i]);
117 img_mark_buffer_undo[i] = NULL;
122 /* draw (area) of pixbuf */
123 void draw_image(int x, int y, int w, int h)
125 GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
126 int window_width, window_height, x_offset, y_offset;
127 gdk_drawable_get_size (draw, &window_width, &window_height);
128 double _r, _g, _b, _y, _u, _v, u_palette, v_palette;
129 int _c, preview_asis = 0;
137 unsigned char compose[w*3];
143 data = gdk_pixbuf_get_pixels(img_pixbuf);
144 rs = gdk_pixbuf_get_rowstride(img_pixbuf);
146 /* this should not happen */
147 if (window_width < img_width*img_scale_x/16)
148 window_width = img_width*img_scale_x/16;
149 if (window_height < img_height*img_scale_y/16)
150 window_height = img_height*img_scale_y/16;
152 /* we need to calculate an offset, since the drawing area is now larger */
153 x_offset = (window_width - img_width*img_scale_x/16) / 2;
154 y_offset = (window_height - img_height*img_scale_y/16) / 2;
156 /* clip to window size */
159 if (x >= window_width)
160 x = window_width - 1;
163 if (y >= window_height)
164 y = window_height - 1;
165 if (x + w > window_width)
166 w = window_width - x;
169 if (y + h > window_height)
170 h = window_height - y;
174 /* draw top border */
176 int temp = (h+y >= y_offset) ? y_offset-y : h; /* height */
177 gdk_draw_rectangle(draw, img_drawing_area->style->bg_gc[GTK_WIDGET_STATE(img_drawing_area)], TRUE, x, y, w, (h+y >= y_offset) ? y_offset-y : h);
184 /* draw bottom border */
185 if (y+h >= y_offset+img_height*img_scale_y/16) {
186 int temp = (y < y_offset+img_height*img_scale_y/16) ? y_offset+img_height*img_scale_y/16 : y; /* y start */
187 gdk_draw_rectangle(draw, img_drawing_area->style->bg_gc[GTK_WIDGET_STATE(img_drawing_area)], TRUE, x, temp, w, h - (temp-y));
193 /* draw left border */
195 int temp = (w+x >= x_offset) ? x_offset-x : w; /* width */
196 gdk_draw_rectangle(draw, img_drawing_area->style->bg_gc[GTK_WIDGET_STATE(img_drawing_area)], TRUE, x, y, (w+x >= x_offset) ? x_offset-x : w, h);
203 /* draw right border */
204 if (x+w >= x_offset+img_width*img_scale_x/16) {
205 int temp = (x < x_offset+img_width*img_scale_x/16) ? x_offset+img_width*img_scale_x/16 : x; /* x start **/
206 gdk_draw_rectangle(draw, img_drawing_area->style->bg_gc[GTK_WIDGET_STATE(img_drawing_area)], TRUE, temp, y, w - (temp-x), h);
215 if (img_grey_buffer) {
217 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);
218 /* check for white color (no change) */
219 if (mark_palette[mark_selected].r == 255 && mark_palette[mark_selected].g == 255 && mark_palette[mark_selected].r == 255)
222 /* compose image (segment) line by line */
223 for (i = 0; i < h; i++) {
224 for (j = 0; j < w; j++) {
225 if (preview && !rendered && !flowview) {
226 /* apply selected color from palette to all pixles */
227 _r = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3] / 255.0F;
228 _g = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1] / 255.0F;
229 _b = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2] / 255.0F;
230 rgb2yuv_pixle(_r, _g, _b, &_y, &_u, &_v);
231 _y = (_y - 0.5) * mark_palette[mark_selected].contrast + 0.5;
232 _y += mark_palette[mark_selected].bright;
238 yuv2rgb_pixle(_y, _u, _v, &_r, &_g, &_b);
240 yuv2rgb_pixle(_y, u_palette, v_palette, &_r, &_g, &_b);
261 compose[j*3] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3];
262 compose[j*3+1] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+1];
263 compose[j*3+2] = img_grey_buffer[((j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y))*3+2];
265 c = img_mark_buffer[(j+x)*16/img_scale_x+img_width*((i+y)*16/img_scale_y)];
266 if (c > 0 && !flowview && !(rendered && preview)) {
268 if (c-1 == mark_selected) {
275 compose[j*3+2] = 128;
278 compose[j*3] = mark_palette[c-1].r;
279 compose[j*3+1] = mark_palette[c-1].g;
280 compose[j*3+2] = mark_palette[c-1].b;
284 memcpy(data + rs*(i+y) + x*3, compose, w*3);
287 for (i = 0; i < h; i++)
288 memset(data + rs*(i+y) + x*3, 0, w*3);
291 gdk_draw_pixbuf(draw, NULL, img_pixbuf, x, y, x+x_offset, y+y_offset, w, h, GDK_RGB_DITHER_NONE, 0, 0);
295 /* plot brush on mark buffer */
296 void paint_brush(int x, int y, int size, int paint)
298 GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
299 int window_width, window_height;
300 gdk_drawable_get_size (draw, &window_width, &window_height);
302 /* we need to calculate an offset, since the drawing area is now larger */
303 x -= (window_width - img_width*img_scale_x/16) / 2;
304 y -= (window_height - img_height*img_scale_y/16) / 2;
306 x = x*16/img_scale_x;
307 y = y*16/img_scale_y;
309 if (!img_mark_buffer || flowview)
312 int x1 = x - size + 1;
313 int x2 = x + size - 1;
314 int y1 = y - size + 1;
315 int y2 = y + size - 1;
326 if (y1 >= img_height)
330 if (y2 >= img_height)
335 /* only paint color, if paint is set */
337 paint = mark_selected + 1;
339 for (i = y1; i <= y2; i++) {
340 for (j = x1; j <= x2; j++) {
341 img_mark_buffer[j+img_width*i] = paint;
346 void erase_mark(int index)
350 if (!img_mark_buffer)
353 /* no index, erase all */
355 memset(img_mark_buffer, 0, img_width * img_height);
359 /* only erase indexed color */
360 for (i = 0; i < img_width * img_height; i++) {
361 if (img_mark_buffer[i] == index)
362 img_mark_buffer[i] = 0;
366 void move_mark(int x, int y)
371 if (!img_mark_buffer || undo_current == 0)
374 src = img_mark_buffer_undo[undo_current-1];
378 if (y < 0 || (y == 0 && x < 0)) {
379 /* move up in memory */
380 for (j = 0; j < img_height; j++) {
381 for (i = 0; i < img_width; i++) {
382 if (i < x || i >= img_width+x || j < y || j >= img_height+y)
383 img_mark_buffer[j*img_width+i] = 0;
385 img_mark_buffer[j*img_width+i] = src[(j-y)*img_width+(i-x)];
389 /* move down in memory */
390 for (j = img_height-1; j >= 0; j--) {
391 for (i = img_width-1; i >= 0; i--) {
392 if (i < x || i >= img_width+x || j < y || j >= img_height+y)
393 img_mark_buffer[j*img_width+i] = 0;
395 img_mark_buffer[j*img_width+i] = src[(j-y)*img_width+(i-x)];
401 void copy_mark_to_undo(void)
403 anything_modified = 1;
405 if (!img_mark_buffer)
408 if (undo_current < UNDO_MAX) {
409 /* allocate new undobuffer and append */
410 if (!img_mark_buffer_undo[undo_current])
411 img_mark_buffer_undo[undo_current] = malloc(img_width*img_height);
412 if (!img_mark_buffer_undo[undo_current])
416 /* shift and use oldest undobuffer */
417 unsigned char *temp = img_mark_buffer_undo[0];
419 for (i = 0; i < UNDO_MAX - 1; i++)
420 img_mark_buffer_undo[i] = img_mark_buffer_undo[i+1];
421 img_mark_buffer_undo[UNDO_MAX - 1] = temp;
423 undo_num = undo_current;
424 //printf("storing undo #%d\n", undo_current-1);
425 memcpy(img_mark_buffer_undo[undo_current-1], img_mark_buffer, img_width*img_height);
426 button_down_x_undo[undo_current-1] = button_down_x;
427 button_down_y_undo[undo_current-1] = button_down_y;
430 void copy_undo_to_mark(int redo)
432 if (!img_mark_buffer)
435 //printf("num is %d\n", undo_num);
437 /* nothing to undo */
438 if (undo_current == 0)
441 /* if we are at the end of the history, we need to add the current image to undo history */
442 if (undo_current == undo_num) {
447 //printf("restore undo #%d\n", undo_current);
449 /* nothing to redo */
450 if (undo_current >= undo_num-1)
453 //printf("restore undo #%d\n", undo_current);
455 memcpy(img_mark_buffer, img_mark_buffer_undo[undo_current], img_width*img_height);
456 button_down_x = button_down_x_undo[undo_current];
457 button_down_y = button_down_y_undo[undo_current];
460 void copy_color(int index)
464 if (img_mark_buffer_copy)
465 free(img_mark_buffer_copy);
466 img_mark_buffer_copy = malloc(img_width*img_height);
467 if (!img_mark_buffer_copy)
470 memcpy(img_mark_buffer_copy, img_mark_buffer, img_width*img_height);
471 copy_width = img_width;
472 copy_height = img_height;
474 /* erase indexed color except given index */
475 for (i = 0; i < img_width * img_height; i++) {
476 if (index && img_mark_buffer_copy[i] != index)
477 img_mark_buffer_copy[i] = 0;
481 void paste_color(void)
485 if (!img_mark_buffer_copy)
488 if (copy_width != img_width || copy_height != img_height) {
489 printerror("Image in copy buffer has different dimenstions.");
493 /* paste indexed pixles */
494 for (i = 0; i < img_width * img_height; i++) {
495 if (img_mark_buffer_copy[i])
496 img_mark_buffer[i] = img_mark_buffer_copy[i];