2 #include <gdk/gdkkeysyms.h>
10 #include "../src/mark.h"
11 #include "../src/ppm.h"
12 #include "../src/yuv.h"
13 #include "../src/dir_seperator.h"
14 #include "../lib/darray.h"
15 #include "../lib/colorize.h"
19 #define min(x,y) ((x < y) ? x : y)
21 struct colorize_priv {
29 static void colorize_destroy(GtkWidget *widget, gpointer priv)
31 struct colorize_priv *cp = (struct colorize_priv *) priv;
33 gtk_widget_destroy(cp->window);
34 g_object_unref(cp->pixbuf);
38 static gboolean colorize_key_press(GtkWidget *widget, GdkEventKey *event, gpointer priv)
40 switch (event->keyval) {
43 if (event->state & GDK_CONTROL_MASK) {
44 gtk_widget_destroy(widget);
48 ;//printf("%x\n", event->keyval);
54 static void save_event(gpointer *priv)
56 struct colorize_priv *cp = (struct colorize_priv *) priv;
59 unsigned char *buffer;
61 char *filename = NULL;
63 dialog = gtk_file_chooser_dialog_new("Select file to save colorized image",
64 GTK_WINDOW(main_window),
65 GTK_FILE_CHOOSER_ACTION_SAVE,
66 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
67 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
70 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), cp->folder);
71 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), cp->filename);
72 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
73 filename = strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
76 gtk_widget_destroy(dialog);
81 data = gdk_pixbuf_get_pixels(cp->pixbuf);
82 rs = gdk_pixbuf_get_rowstride(cp->pixbuf);
83 buffer = malloc(cp->width*cp->height*3);
85 for (i = 0; i < cp->height; i++) {
86 for (j = 0; j < cp->width; j++) {
87 buffer[(i*cp->width+j)*3+0] = data[i*rs+j*3+0];
88 buffer[(i*cp->width+j)*3+1] = data[i*rs+j*3+1];
89 buffer[(i*cp->width+j)*3+2] = data[i*rs+j*3+2];
93 save_img(buffer, cp->width, cp->height, filename, 0);
96 static void dummy_event(gpointer *priv)
100 static void close_event(gpointer *priv)
102 struct colorize_priv *cp = (struct colorize_priv *) priv;
104 gtk_widget_destroy(cp->window);
107 void colorize_image(void)
109 darray_t *gI = NULL, *cI = NULL, *markIm = NULL, *ntscIm = NULL;
110 double *ptr, *ptr2, *ptr3;
112 int width = img_width, height = img_height;
113 int features, change_bc;
120 GtkWidget *colorize_window;
123 GtkWidget *root_menu;
125 GtkWidget *menu_item;
126 struct colorize_priv *cp;
134 /* generate grey image array */
135 dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
136 gI = darrayCreate(4, dims);
138 printerror("No memory: failed to create grey image array");
141 ptr = darrayGetPr(gI);
142 img2array(img_grey_buffer, img_width, img_height, ptr, width, height);
144 /* generade marked color image */
145 dims[0] = width; dims[1] = height; dims[2] = 3; dims[3] = 1;
146 cI = darrayCreate(4, dims);
148 printerror("No memory: failed to create marked image array");
151 ptr = darrayGetPr(cI);
152 img2array(img_grey_buffer, img_width, img_height, ptr, width, height);
154 for (i = 0; i < img_height; i++) {
155 for (j = 0; j < img_width; j++) {
156 /* do not apply mask on index 0 */
157 c = img_mark_buffer[i*img_width+j];
160 /* check for any brightness/contrast change */
161 if (mark_palette[c-1].bright != 0 || mark_palette[c-1].contrast != 1)
163 /* do not apply white pixles, this meas: keep original color */
164 if (mark_palette[c-1].r == 255 && mark_palette[c-1].g == 255 && mark_palette[c-1].b == 255)
166 ptr[i*width+j] = mark_palette[c-1].r / 255.0F;
167 ptr[i*width+j + width*height] = mark_palette[c-1].g / 255.0F;
168 ptr[i*width+j + width*height*2] = mark_palette[c-1].b / 255.0F;
172 // convert grey image into YUV
173 ptr = darrayGetPr(gI);
174 rgb2yuv(ptr, ptr, width, height);
176 // convert marked image into YUV
177 ptr = darrayGetPr(cI);
178 rgb2yuv(ptr, ptr, width, height);
180 /* create color mask and ntsc arrays for the colorization process */
181 dims[0] = width; dims[1] = height; dims[2] = 1;
182 markIm = darrayCreate(3, dims);
184 printerror("No memory: failed to create color array");
187 features = (change_bc) ? 4 : 2;
188 dims[0] = width; dims[1] = height; dims[2] = features+1; dims[3] = 1;
189 ntscIm = darrayCreate(4, dims);
191 printerror("No memory: failed to create ntsc array");
195 /* apply mask to markIm */
196 ptr = darrayGetPr(markIm);
197 for (i = 0; i < img_height; i++) {
198 for (j = 0; j < img_width; j++) {
199 /* do not apply mask on index 0 */
200 c = img_mark_buffer[i*img_width+j];
201 ptr[i*width+j] = (c == 0) ? 0.0F : 1.0F;
205 // generate NTSC image: use luminance from original image and chrominance from original or marked image
206 ptr = darrayGetPr(gI);
207 ptr2 = darrayGetPr(cI);
208 ptr3 = darrayGetPr(ntscIm);
209 memcpy(ptr3, ptr, width * height * sizeof(double));
210 for (i = 0; i < img_height; i++) {
211 for (j = 0; j < img_width; j++) {
212 c = img_mark_buffer[i*img_width+j];
214 ptr3[width * height + width * i + j] = ptr[width * height + width * i + j];
215 ptr3[width * height * 2 + width * i + j] = ptr[width * height * 2 + width * i + j];
217 ptr3[width * height + width * i + j] = ptr2[width * height + width * i + j];
218 ptr3[width * height * 2 + width * i + j] = ptr2[width * height * 2 + width * i + j];
222 /* if we have a change, we modify brightness+contrast first */
224 /* apply brightness and contrast from makred pixles to grey image */
225 for (i = 0; i < height; i++) {
226 for (j = 0; j < width; j++) {
227 ptr3[i*width+j] = ptr[i*width+j];
228 if (j < img_width && i < img_height) {
229 /* use unchanged brightness and contrast on index 0 */
230 c = img_mark_buffer[i*img_width+j];
234 ptr3[i*width+j + width*height*3] = 0;
235 ptr3[i*width+j + width*height*4] = 0.1;
237 ptr3[i*width+j + width*height*3] = mark_palette[c-1].bright / 10.0;
238 ptr3[i*width+j + width*height*4] = mark_palette[c-1].contrast / 10.0;
244 /* destroy temporary gI and cI */
250 /* render u and v change */
251 rc = colorize(ntscIm, markIm, NULL, NULL, 5, 1, 0);
253 printerror("No memory! Use smaller image or add more memory.");
257 /* if we have a change, we apply brightness+contrast from ntscIm */
259 ptr = darrayGetPr(ntscIm);
260 ptr2 = darrayGetPr(ntscIm);
261 for (i = 0; i < img_height; i++) {
262 for (j = 0; j < img_width; j++) {
264 ptr2[width * i + j] = (ptr2[width * i + j] - 0.5) * ptr[width * height * 4 + width * i + j] * 10.0 + 0.5;
265 /* apply brightness */
266 ptr2[width * i + j] += ptr[width * height * 3 + width * i + j] * 10.0;
267 if (ptr2[width * i + j] < 0)
268 ptr2[width * i + j] = 0;
269 if (ptr2[width * i + j] > 1)
270 ptr2[width * i + j] = 1;
275 if (img_scale_y == img_scale_x*2)
280 /* apply YUV to pixbuffer and display */
281 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, img_width, img_height * zoom_field);
282 ptr = darrayGetPr(ntscIm);
283 yuv2rgb(ptr, ptr, width, height);
284 data = gdk_pixbuf_get_pixels(pixbuf);
285 rs = gdk_pixbuf_get_rowstride(pixbuf);
286 for (i = 0; i < img_height*zoom_field; i++) {
287 for (j = 0; j < img_width; j++) {
288 c = ptr[(i/zoom_field)*width+j] * 255.0F;
293 data[i*rs + 3*j + 0] = c;
294 c = ptr[(i/zoom_field)*width+j + width*height] * 255.0F;
299 data[i*rs + 3*j + 1] = c;
300 c = ptr[(i/zoom_field)*width+j + width*height*2] * 255.0F;
305 data[i*rs + 3*j + 2] = c;
310 image = gtk_image_new_from_pixbuf(pixbuf);
311 gtk_widget_show(image);
313 darrayDestroy(markIm);
315 darrayDestroy(ntscIm);
320 /* private structure */
321 cp = calloc(sizeof(struct colorize_priv), 1);
324 colorize_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
325 gtk_window_set_title(GTK_WINDOW(colorize_window), "Colorized");
326 g_signal_connect(colorize_window, "destroy", G_CALLBACK(colorize_destroy), cp);
327 g_signal_connect(colorize_window, "key_press_event", G_CALLBACK(colorize_key_press), cp);
329 cp->window = colorize_window;
331 cp->width = img_width*zoom_field;
332 cp->height = img_height*zoom_field;
333 p = frame_list[timeline_selected].filename;
334 while((q = strchr(p, DIR_SEPERATOR)))
336 strcpy(cp->folder, frame_list[timeline_selected].filename);
337 cp->folder[p - frame_list[timeline_selected].filename] = '\0';
338 sprintf(cp->filename, "colorized_%s", p);
341 menu_bar = gtk_menu_bar_new();
342 gtk_widget_show(menu_bar);
343 menu = gtk_menu_new();
344 root_menu = gtk_menu_item_new_with_mnemonic("_File");
345 gtk_widget_show(root_menu);
347 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE_AS, NULL);
348 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
349 g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(save_event), cp);
350 gtk_widget_show(menu_item);
351 menu_item = gtk_separator_menu_item_new();
352 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
353 g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(dummy_event), cp);
354 gtk_widget_show(menu_item);
355 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL);
356 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
357 g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(close_event), cp);
358 gtk_widget_show(menu_item);
359 gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu), menu);
360 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), root_menu);
362 /* create vbox (complete window) */
363 vbox = gtk_vbox_new(FALSE, 0);
364 gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
365 gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 2);
366 gtk_widget_show(vbox);
368 gtk_container_add(GTK_CONTAINER(colorize_window), vbox);
369 gtk_widget_show(colorize_window);
374 darrayDestroy(markIm);
375 darrayDestroy(ntscIm);