Fix run length encoding of marked image, bump to version 0.8
[colorize.git] / gui / fill.c
1 #include <gtk/gtk.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include "main.h"
6 #include "image.h"
7 #include "../src/mark.h"
8 #include "palette.h"
9 #include "fill.h"
10
11 /* fill makred area with different color */
12 void fill(int x, int y, int clear)
13 {
14         GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
15         int window_width, window_height;
16         unsigned char *img_fill_buffer;
17         unsigned char old, new = 0;
18         int filled;
19         gdk_drawable_get_size (draw, &window_width, &window_height);
20
21         if (!img_mark_buffer)
22                 return;
23
24         img_fill_buffer = calloc(img_width*img_height, sizeof(*img_fill_buffer));
25         if (!img_fill_buffer)
26                 return;
27
28         /* we need to calculate an offset, since the drawing area is now larger */
29         x -= (window_width - img_width*img_scale_x/16) / 2;
30         y -= (window_height - img_height*img_scale_y/16) / 2;
31
32         x = x*16/img_scale_x;
33         y = y*16/img_scale_y;
34
35         if (x < 0 || x >= img_width || y < 0 || y >= img_height)
36                 return;
37
38         old = img_mark_buffer[img_width*y+x];
39         if (!clear)
40                 new = mark_selected + 1;
41         if (old == new)
42                 goto done;
43
44         /* set seed */
45         img_mark_buffer[img_width*y+x] = new;
46         img_fill_buffer[img_width*y+x] = 1;
47
48         do {
49                 filled = 0;
50                 /* top to bottom */
51                 for (y = 0; y < img_height; y++) {
52                         /* left to right */
53                         for (x = 0; x < img_width; x++) {
54                                 /* check for filled pixle */
55                                 if (!img_fill_buffer[img_width*y+x])
56                                         continue;
57                                 /* if right neighbor pixle is old, set to new */
58                                 if (x < img_width-1 && img_mark_buffer[img_width*y+(x+1)] == old) {
59                                         img_mark_buffer[img_width*y+(x+1)] = new;
60                                         img_fill_buffer[img_width*y+(x+1)] = 1;
61                                         filled++;
62                                 }
63                                 /* if lower neighbor pixle is old, set to new */
64                                 if (y < img_height-1 && img_mark_buffer[img_width*(y+1)+x] == old) {
65                                         img_mark_buffer[img_width*(y+1)+x] = new;
66                                         img_fill_buffer[img_width*(y+1)+x] = 1;
67                                         filled++;
68                                 }
69                                 /* fill8: if lower right neighbor pixle is old, set to new */
70                                 if (old && x < img_width-1 && y < img_height-1 && img_mark_buffer[img_width*(y+1)+(x+1)] == old) {
71                                         img_mark_buffer[img_width*(y+1)+(x+1)] = new;
72                                         img_fill_buffer[img_width*(y+1)+(x+1)] = 1;
73                                         filled++;
74                                 }
75                         }
76                         /* right to left */
77                         for (x = img_width - 1; x >= 0; x--) {
78                                 /* check for filled pixle */
79                                 if (!img_fill_buffer[img_width*y+x])
80                                         continue;
81                                 /* if left neighbor pixle is old, set to new */
82                                 if (x > 0 && img_mark_buffer[img_width*y+(x-1)] == old) {
83                                         img_mark_buffer[img_width*y+(x-1)] = new;
84                                         img_fill_buffer[img_width*y+(x-1)] = 1;
85                                         filled++;
86                                 }
87                                 /* if lower neighbor pixle is old, set to new */
88                                 if (y < img_height-1 && img_mark_buffer[img_width*(y+1)+x] == old) {
89                                         img_mark_buffer[img_width*(y+1)+x] = new;
90                                         img_fill_buffer[img_width*(y+1)+x] = 1;
91                                         filled++;
92                                 }
93                                 /* if fill8. lower left neighbor pixle is old, set to new */
94                                 if (old && x > 0 && y < img_height-1 && img_mark_buffer[img_width*(y+1)+(x-1)] == old) {
95                                         img_mark_buffer[img_width*(y+1)+(x-1)] = new;
96                                         img_fill_buffer[img_width*(y+1)+(x-1)] = 1;
97                                         filled++;
98                                 }
99                         }
100                 }
101                 /* bottom to top */
102                 for (y = img_height-1; y >= 0; y--) {
103                         /* left to right */
104                         for (x = 0; x < img_width; x++) {
105                                 /* check for filled pixle */
106                                 if (!img_fill_buffer[img_width*y+x])
107                                         continue;
108                                 /* if right neighbor pixle is old, set to new */
109                                 if (x < img_width-1 && img_mark_buffer[img_width*y+(x+1)] == old) {
110                                         img_mark_buffer[img_width*y+(x+1)] = new;
111                                         img_fill_buffer[img_width*y+(x+1)] = 1;
112                                         filled++;
113                                 }
114                                 /* if upper neighbor pixle is old, set to new */
115                                 if (y > 0 && img_mark_buffer[img_width*(y-1)+x] == old) {
116                                         img_mark_buffer[img_width*(y-1)+x] = new;
117                                         img_fill_buffer[img_width*(y-1)+x] = 1;
118                                         filled++;
119                                 }
120                                 /* fill8: if upper right neighbor pixle is old, set to new */
121                                 if (old && x < img_width-1 && y > 0 && img_mark_buffer[img_width*(y-1)+(x+1)] == old) {
122                                         img_mark_buffer[img_width*(y-1)+(x+1)] = new;
123                                         img_fill_buffer[img_width*(y-1)+(x+1)] = 1;
124                                         filled++;
125                                 }
126                         }
127                         /* right to left */
128                         for (x = img_width - 1; x >= 0; x--) {
129                                 /* check for filled pixle */
130                                 if (!img_fill_buffer[img_width*y+x])
131                                         continue;
132                                 /* if left neighbor pixle is old, set to new */
133                                 if (x > 0 && img_mark_buffer[img_width*y+(x-1)] == old) {
134                                         img_mark_buffer[img_width*y+(x-1)] = new;
135                                         img_fill_buffer[img_width*y+(x-1)] = 1;
136                                         filled++;
137                                 }
138                                 /* if upper neighbor pixle is old, set to new */
139                                 if (y > 0 && img_mark_buffer[img_width*(y-1)+x] == old) {
140                                         img_mark_buffer[img_width*(y-1)+x] = new;
141                                         img_fill_buffer[img_width*(y-1)+x] = 1;
142                                         filled++;
143                                 }
144                                 /* if upper leftneighbor pixle is old, set to new */
145                                 if (old && x > 0 && y > 0 && img_mark_buffer[img_width*(y-1)+(x-1)] == old) {
146                                         img_mark_buffer[img_width*(y-1)+(x-1)] = new;
147                                         img_fill_buffer[img_width*(y-1)+(x-1)] = 1;
148                                         filled++;
149                                 }
150                         }
151                 }
152 //              printf("filled %d pixles in this iteration\n", filled);
153         } while (filled);
154
155 done:
156         free(img_fill_buffer);
157 }