Fix run length encoding of marked image, bump to version 0.8
[colorize.git] / gui / palette.c
1 #include <gtk/gtk.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "main.h"
5 #include "../src/mark.h"
6 #include "../src/yuv.h"
7 #include "palette.h"
8 #include "timeline.h"
9 #include "image.h"
10
11 int mark_selected = 0;
12
13 #define COLOR_WIDTH 100
14 #define COLOR_HEIGHT 20
15
16 static char *bc_pic[] = {
17         "     *     ",
18         " *   *   * ",
19         "  *     *  ",
20         "    ***    ",
21         "   *** *   ",
22         "** *** * **",
23         "   *** *   ",
24         "    ***    ",
25         "  *     *  ",
26         " *   *   * ",
27         "     *     ",
28 };
29
30 static char *alpha_pic[] = {
31         "   ***    *",
32         "  *   *   *",
33         " *     * * ",
34         " *     * * ",
35         "*       *  ",
36         "*       *  ",
37         "*       *  ",
38         " *     **  ",
39         " *     **  ",
40         "  *   *  * ",
41         "   ***    *",
42 };
43 static char *asis_pic[] = {
44         "     **           ****          **      ****    ",
45         "    ****        ********        **    ********  ",
46         "   **  **      ***    ***       **   ***    *** ",
47         "  **    **    **        **      **  **        **",
48         " **      **   **                **  **          ",
49         "**        **   **               **   **         ",
50         "************    ******          **    ******    ",
51         "************      ******        **      ******  ",
52         "**        **           **       **           ** ",
53         "**        **            **      **            **",
54         "**        **  **        **      **  **        **",
55         "**        **   ***    ***       **   ***    *** ",
56         "**        **    ********        **    ********  ",
57         "**        **      ****          **      ****    ",
58 };
59
60 static GdkPixbuf *draw_pixpuf(int i)
61 {
62         GdkPixbuf *pixbuf;
63         guchar *data;
64         int j, jj, k, kk, rs;
65         int cr, cg, cb, asis = 0;
66         float bright, contrast, alpha;
67         double r, g, b, y, u, v, pat;
68
69         cr = mark_palette[i].r;
70         cg = mark_palette[i].g;
71         cb = mark_palette[i].b;
72         bright = mark_palette[i].bright;
73         contrast = mark_palette[i].contrast;
74         alpha = mark_palette[i].alpha;
75         r = cr / 255.0;
76         g = cg / 255.0;
77         b = cb / 255.0;
78         if (cr == 255 && cg == 255 && cb == 255)
79                 asis = 1;
80         rgb2yuv_pixle(r, g, b, &y, &u, &v);
81
82         pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, COLOR_WIDTH, COLOR_HEIGHT);
83         data = gdk_pixbuf_get_pixels(pixbuf);
84         rs = gdk_pixbuf_get_rowstride(pixbuf);
85         if (asis) {
86                 for (k = 0; k < COLOR_WIDTH; k++) {
87                         if (k >= COLOR_HEIGHT+3) {
88                                 if (alpha < 1) {
89                                         pat = ((k>>3)&1) ? 0.5 : 0.75;
90                                         r = alpha + pat * (1-alpha);
91                                         g = alpha + pat * (1-alpha);
92                                         b = alpha + pat * (1-alpha);
93                                 } else {
94                                         r = 1;
95                                         g = 1;
96                                         b = 1;
97                                 }
98                                 cr = r * 255.0F;
99                                 if (cr < 0)
100                                         cr = 0;
101                                 else if (cr > 255)
102                                         cr = 255;
103                                 cg = g * 255.0F;
104                                 if (cg < 0)
105                                         cg = 0;
106                                 else if (cg > 255)
107                                         cg = 255;
108                                 cb = b * 255.0F;
109                                 if (cb < 0)
110                                         cb = 0;
111                                 else if (cb > 255)
112                                         cb = 255;
113                         } else
114                         if (k >= COLOR_HEIGHT) {
115                                 cr = 255;
116                                 cg = 255;
117                                 cb = 255;
118                         }
119                         for (j = 0; j < COLOR_HEIGHT; j++) {
120                                 data[j * rs + k * 3 + 0] = cr;
121                                 data[j * rs + k * 3 + 1] = cg;
122                                 data[j * rs + k * 3 + 2] = cb;
123                         }
124                 }
125         } else {
126                 for (k = 0; k < COLOR_WIDTH; k++) {
127                         /* we use height as horizontal size of original color area */
128                         if (k >= COLOR_HEIGHT+3) {
129                                 y = (double)(k-COLOR_HEIGHT-3) / (double)((COLOR_WIDTH-COLOR_HEIGHT-3)-1);
130                                 y = (y - 0.5) * contrast + 0.5;
131                                 y += bright;
132                                 if (y < 0)
133                                         y = 0;
134                                 if (y > 1)
135                                         y = 1;
136                                 yuv2rgb_pixle(y, u, v, &r, &g, &b);
137                                 if (alpha < 1) {
138                                         pat = ((k>>3)&1) ? 0.5 : 0.75;
139                                         r = r * alpha + pat * (1-alpha);
140                                         g = g * alpha + pat * (1-alpha);
141                                         b = b * alpha + pat * (1-alpha);
142                                 }
143                                 cr = r * 255.0F;
144                                 if (cr < 0)
145                                         cr = 0;
146                                 else if (cr > 255)
147                                         cr = 255;
148                                 cg = g * 255.0F;
149                                 if (cg < 0)
150                                         cg = 0;
151                                 else if (cg > 255)
152                                         cg = 255;
153                                 cb = b * 255.0F;
154                                 if (cb < 0)
155                                         cb = 0;
156                                 else if (cb > 255)
157                                         cb = 255;
158                         } else
159                         if (k >= COLOR_HEIGHT) {
160                                 cr = 255;
161                                 cg = 255;
162                                 cb = 255;
163                         }
164                         for (j = 0; j < COLOR_HEIGHT; j++) {
165                                 data[j * rs + k * 3 + 0] = cr;
166                                 data[j * rs + k * 3 + 1] = cg;
167                                 data[j * rs + k * 3 + 2] = cb;
168                         }
169                 }
170         }
171
172         /* indicate a change in alpha */
173         if (alpha < 1) {
174                 for (k = 0, kk = COLOR_HEIGHT - 11; k < 11; k++, kk++) {
175                         for (j = 0, jj = COLOR_HEIGHT - 11; j < 11; j++, jj++) {
176                                 if (alpha_pic[j][k] == '*') {
177                                         data[jj * rs + kk * 3 + 0] = 255;
178                                         data[jj * rs + kk * 3 + 1] = 0;
179                                         data[jj * rs + kk * 3 + 2] = 0;
180                                 }
181                         }
182                 }
183         }
184
185         /* indicate a change in brightness + contrast */
186         if (bright != 0 || contrast != 1) {
187                 for (k = 0; k < 11; k++) {
188                         for (j = 0; j < 11; j++) {
189                                 if (bc_pic[j][k] == '*') {
190                                         data[j * rs + k * 3 + 0] = 255;
191                                         data[j * rs + k * 3 + 1] = 0;
192                                         data[j * rs + k * 3 + 2] = 0;
193                                 }
194                         }
195                 }
196         }
197
198         /* indicate that the color is as it is on the image */
199         if (asis) {
200                 for (k = 0, kk = (COLOR_WIDTH - COLOR_HEIGHT - 3 - 48) / 2 + COLOR_HEIGHT + 3; k < 48; k++, kk++) {
201                         for (j = 0, jj = COLOR_HEIGHT / 2 - 7; j < 14; j++, jj++) {
202                                 if (asis_pic[j][k] == '*') {
203                                         data[jj * rs + kk * 3 + 0] = 255;
204                                         data[jj * rs + kk * 3 + 1] = 0;
205                                         data[jj * rs + kk * 3 + 2] = 0;
206                                 }
207                         }
208                 }
209         }
210
211         return pixbuf;
212 }
213
214 void create_palette(void)
215 {
216         GtkListStore *palette_store;
217         GtkTreeIter   iter;
218         int i;
219         char number[10];
220         GdkPixbuf *color;
221
222         for (i = 0; i < 255; i++) {
223                 strcpy(mark_palette[i].name, "");
224                 mark_palette[i].r = 0;
225                 mark_palette[i].g = 0;
226                 mark_palette[i].b = 0;
227                 mark_palette[i].bright = 0;
228                 mark_palette[i].contrast = 1;
229                 mark_palette[i].alpha = 1;
230         }
231
232         strcpy(mark_palette[0].name, "red");
233         mark_palette[0].r = 255;
234         mark_palette[0].g = 0;
235         mark_palette[0].b = 0;
236         strcpy(mark_palette[1].name, "green");
237         mark_palette[1].r = 0;
238         mark_palette[1].g = 255;
239         mark_palette[1].b = 0;
240         strcpy(mark_palette[2].name, "blue");
241         mark_palette[2].r = 0;
242         mark_palette[2].g = 0;
243         mark_palette[2].b = 255;
244
245         palette_store = gtk_list_store_new(3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING);
246         gtk_tree_view_set_model(GTK_TREE_VIEW(palette_treeview), GTK_TREE_MODEL(palette_store));
247         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(palette_treeview), FALSE);
248
249         for (i = 0; i < 255; i++) {
250                 gtk_list_store_append(palette_store, &iter);
251                 sprintf(number, "%d", i+1);
252                 color = draw_pixpuf(i);
253                 gtk_list_store_set(palette_store, &iter, 0, number, 1, color, 2, mark_palette[i].name, -1);
254                 g_object_unref(color);
255                 if (i == mark_selected) {
256                         GtkTreeSelection *selection;
257                         GtkTreePath *path;
258                         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(palette_treeview));
259                         gtk_tree_selection_select_iter(selection, &iter);
260                         path = gtk_tree_model_get_path(GTK_TREE_MODEL(palette_store), &iter);
261                         gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(palette_treeview), path, NULL, FALSE, 0,0);
262                         gtk_tree_path_free(path);
263                 }
264         }
265
266         g_object_unref(palette_store);
267
268 }
269
270 int get_iter_by_path_name(GtkTreeIter *iter, GtkTreeModel *model, int entry)
271 {
272         char path_name[10];
273
274         sprintf(path_name, "%d", entry);
275         if (gtk_tree_model_get_iter_from_string(model, iter, path_name))
276                 return 1;
277         return 0;
278 }
279
280 void update_color(int entry)
281 {
282         GdkPixbuf *color;
283         GtkTreeIter iter;
284         GtkTreeModel *model;
285
286         color = draw_pixpuf(entry);
287
288         model = gtk_tree_view_get_model(GTK_TREE_VIEW(palette_treeview));
289         if (get_iter_by_path_name(&iter, model, entry))
290                 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 1, color, 2, mark_palette[entry].name, -1);
291 }
292
293 void pick_color(int x, int y)
294 {
295         GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
296         int window_width, window_height;
297         unsigned char c;
298         gdk_drawable_get_size (draw, &window_width, &window_height);
299
300         if (!img_mark_buffer)
301                 return;
302
303         /* we need to calculate an offset, since the drawing area is now larger */
304         x -= (window_width - img_width*img_scale_x/16) / 2;
305         y -= (window_height - img_height*img_scale_y/16) / 2;
306
307         x = x*16/img_scale_x;
308         y = y*16/img_scale_y;
309
310         if (x < 0 || x >= img_width || y < 0 || y >= img_height)
311                 return;
312
313         c = img_mark_buffer[img_width*y+x];
314         if (c > 0) {
315                 GtkTreeIter iter;
316                 GtkTreeModel *model;
317                 GtkTreeSelection *selection;
318                 GtkTreePath *path;
319
320                 mark_selected = c - 1;
321                 model = gtk_tree_view_get_model(GTK_TREE_VIEW(palette_treeview));
322                 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(palette_treeview));
323                 if (get_iter_by_path_name(&iter, model, mark_selected)) {
324                         gtk_tree_selection_select_iter(selection, &iter);
325                         path = gtk_tree_model_get_path(model, &iter);
326                         gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(palette_treeview), path, NULL, FALSE, 0,0);
327                         gtk_tree_path_free(path);
328                 }
329         }
330 }
331