1 #include "config.h"
2 #include <cstring>
3 #include <cmath>
4 #include <cstdio>
5 #include <cstdlib>
6 #include "filter.h"
7 #include "fractal.h"
8 #include "xthread.h"
9 #include "xerror.h"
10 
11 #define SIZE 64
12 #define SIZE2 8
13 #define AMOUNT 0.005
14 #define DIV 1000.0
15 #define MAXFRAMES 800 * 1000 /*after 800 frames should be OK */
16 struct blurdata {
17     int bckuptime;
18     int counter;
19     struct palette *savedpalette, *palette;
20     unsigned char (*table)[256]; /*Used by blur routines */
21     int n;
22 };
requirement(struct filter * f,struct requirements * r)23 static int requirement(struct filter *f, struct requirements *r)
24 {
25     f->req = *r;
26     r->nimages = 1;
27     r->flags |= IMAGEDATA;
28     r->supportedmask = C256 | TRUECOLOR24 | TRUECOLOR | TRUECOLOR16 | GRAYSCALE;
29     return (f->next->action->requirement(f->next, r));
30 }
31 
blur8(struct filter * f)32 static void blur8(struct filter *f)
33 {
34     struct image *desti = f->image;
35     struct blurdata *s = (struct blurdata *)f->data;
36     unsigned char(*table)[256] = s->table;
37     unsigned int i, i1, im, im1, ipl, ii;
38     if (f->image->palette->type == C256)
39         for (i = im = 0; i < SIZE; i++, im += 256 - s->n) {
40             for (i1 = im1 = 0; i1 < SIZE2; i1++, im1 += s->n * (SIZE / SIZE2)) {
41                 ipl = (im + im1 + 128) >> 8;
42                 ii = i1 * (SIZE / SIZE2);
43                 if (ipl == i && i != ii) {
44                     if (i < ii)
45                         ipl++;
46                     else
47                         ipl--;
48                 }
49                 ii = desti->palette->pixels[i];
50                 table[i1][ii] = (unsigned char)desti->palette->pixels[ipl];
51             }
52         }
53     else
54         for (i = im = desti->palette->start, im *= 256 - s->n;
55              i < (unsigned int)desti->palette->end; i++, im += 256 - s->n) {
56             for (i1 = im1 = desti->palette->start, im1 *= s->n;
57                  i1 < (unsigned int)desti->palette->end; i1++, im1 += s->n) {
58                 ipl = (im + im1 + 128) >> 8;
59                 if (ipl == i && i != i1) {
60                     if (i < i1)
61                         ipl++;
62                     else
63                         ipl--;
64                 }
65                 table[i1][i] = (unsigned char)ipl;
66             }
67         }
68 }
69 
blurtruecolor(struct filter * f)70 static void blurtruecolor(struct filter *f)
71 {
72     struct blurdata *s = (struct blurdata *)f->data;
73     unsigned int i, i1, im, im1;
74     unsigned char(*table)[256] = s->table;
75     for (i = im = 0; i < 256; i++, im += 256 - s->n) {
76         for (i1 = im1 = 0; i1 < 256; i1++, im1 += s->n)
77             table[i1][i] = (unsigned char)((im + im1) >> 8);
78     }
79 }
80 
clear_image2(struct image * img)81 static void clear_image2(struct image *img)
82 {
83     int i;
84     int color = img->palette->pixels[0];
85     int width = img->width * img->bytesperpixel;
86     if (!width)
87         width = (img->width + 7) / 8;
88     for (i = 0; i < img->height; i++)
89         memset(img->currlines[i], color, (size_t)width);
90 }
91 
initialize(struct filter * f,struct initdata * i)92 static int initialize(struct filter *f, struct initdata *i)
93 {
94     struct blurdata *s = (struct blurdata *)f->data;
95     unsigned int x;
96     inhermisc(f, i);
97     s->counter = 0;
98     s->palette->size = SIZE2;
99     for (x = 0; x < SIZE2; x++)
100         s->palette->pixels[x] = x;
101     if (datalost(f, i) || i->image->version != f->imageversion) {
102         s->bckuptime = MAXFRAMES;
103         s->counter = MAXFRAMES;
104         if (i->image->palette->type == C256) {
105             if (s->savedpalette == NULL)
106                 s->savedpalette = clonepalette(i->image->palette);
107             mkblurpalette(i->image->palette);
108         } else {
109             if (s->savedpalette != NULL) {
110                 restorepalette(i->image->palette, s->savedpalette);
111                 destroypalette(s->savedpalette);
112                 s->savedpalette = NULL;
113             }
114         }
115         clear_image2(i->image);
116     }
117     if (!inherimage(f, i, TOUCHIMAGE | IMAGEDATA, 0, 0,
118                     i->image->palette->type == C256 ? s->palette : NULL, 0, 0))
119         return 0;
120     if (f->image->palette->type == C256) {
121         setfractalpalette(f, s->savedpalette);
122     }
123     if (i->image == NULL) {
124         return 0;
125     }
126     return (f->previous->action->initialize(f->previous, i));
127 }
128 
getinstance(const struct filteraction * a)129 static struct filter *getinstance(const struct filteraction *a)
130 {
131     struct filter *f = createfilter(a);
132     struct blurdata *i = (struct blurdata *)calloc(1, sizeof(*i));
133     i->savedpalette = NULL;
134     i->palette =
135         createpalette(0, 256, SMALLITER, 0, 256, NULL, NULL, NULL, NULL, NULL);
136     i->palette->size = SIZE2;
137     i->palette->end = SIZE2;
138     i->table = NULL;
139     f->childimage = NULL;
140     f->data = i;
141     f->name = "Motionblur";
142     return (f);
143 }
144 
destroyinstance(struct filter * f)145 static void destroyinstance(struct filter *f)
146 {
147     struct blurdata *i = (struct blurdata *)f->data;
148     if (i->table != NULL)
149         free(i->table);
150     if (i->savedpalette != NULL)
151         destroypalette(i->savedpalette);
152     destroypalette(i->palette);
153     destroyinheredimage(f);
154     free(f->data);
155     free(f);
156 }
157 
158 /* An part of blur function that should be done paraely */
blur82(void * data,struct taskinfo *,int r1,int r2)159 static void blur82(void *data, struct taskinfo */*task*/, int r1, int r2)
160 {
161     struct filter *f = (struct filter *)data;
162     struct image *srci = f->childimage, *desti = f->image;
163     struct blurdata *s = (struct blurdata *)f->data;
164     unsigned char(*table)[256];
165     int i, im;
166     unsigned char *src, *dest, *srcend;
167 
168     im = srci->width;
169     table = s->table;
170     for (i = r1; i < r2; i++) {
171         src = srci->currlines[i];
172         srcend = src + im;
173         dest = desti->currlines[i];
174         for (; src < srcend; src++, dest++) {
175             dest[0] = table[src[0]][dest[0]];
176         }
177     }
178 }
179 
180 #ifdef SUPPORT16
blur16(void * data,struct taskinfo *,int r1,int r2)181 static void blur16(void *data, struct taskinfo */*task*/, int r1, int r2)
182 {
183     struct filter *f = (struct filter *)data;
184     struct image *srci = f->childimage, *desti = f->image;
185     struct blurdata *s = (struct blurdata *)f->data;
186     struct truec *info = &srci->palette->info.truec;
187     unsigned int rmask = info->rmask;
188     unsigned int gmask = info->gmask;
189     unsigned int bmask = info->bmask;
190     unsigned int n = (unsigned int)s->n;
191     int i;
192     pixel16_t *src, *dest, *srcend;
193     for (i = r1; i < r2; i++) {
194         src = (pixel16_t *)srci->currlines[i];
195         srcend = src + srci->width;
196         dest = (pixel16_t *)desti->currlines[i];
197         for (; src < srcend; src++, dest++) {
198             *dest = interpol(*src, *dest, n, rmask, gmask, bmask);
199         }
200     }
201 }
202 #endif
203 #ifdef STRUECOLOR24
blur24(void * data,struct taskinfo * task,int r1,int r2)204 static void blur24(void *data, struct taskinfo *task, int r1, int r2)
205 {
206     struct filter *f = (struct filter *)data;
207     struct image *srci = f->childimage, *desti = f->image;
208     struct blurdata *s = (struct blurdata *)f->data;
209     unsigned char(*table)[256] = s->table;
210     unsigned char *src, *dest, *srcend;
211     int i, im;
212     im = srci->width * 3;
213     if (!srci->palette->info.truec.byteexact) {
214         x_fatalerror(
215             "Blur filter:unsupported color configuration! Please contact authors.");
216     }
217     for (i = r1; i < r2; i++) {
218         src = srci->currlines[i];
219         srcend = src + im;
220         dest = desti->currlines[i];
221         for (; src < srcend; src += 3, dest += 3) {
222             dest[0] = table[src[0]][dest[0]];
223             dest[1] = table[src[1]][dest[1]];
224             dest[2] = table[src[2]][dest[2]];
225         }
226     }
227 }
228 #endif
blur32(void * data,struct taskinfo *,int r1,int r2)229 static void blur32(void *data, struct taskinfo */*task*/, int r1, int r2)
230 {
231     struct filter *f = (struct filter *)data;
232     struct image *srci = f->childimage, *desti = f->image;
233     struct blurdata *s = (struct blurdata *)f->data;
234     unsigned char(*table)[256] = s->table;
235     unsigned char *src, *dest, *srcend;
236     int i, im;
237     im = srci->width * 4;
238     if (!srci->palette->info.truec.byteexact) {
239         x_fatalerror(
240             "Blur filter:unsupported color configuration! Please contact authors.");
241     }
242     for (i = r1; i < r2; i++) {
243         src = srci->currlines[i];
244         srcend = src + im;
245         dest = desti->currlines[i];
246         switch (f->image->palette->info.truec.missingbyte) {
247             case 3:
248                 for (; src < srcend; src += 4, dest += 4) {
249                     dest[0] = table[src[0]][dest[0]];
250                     dest[1] = table[src[1]][dest[1]];
251                     dest[2] = table[src[2]][dest[2]];
252                     dest[3] = 0xff;
253                 }
254                 break;
255             case 2:
256                 for (; src < srcend; src += 4, dest += 4) {
257                     dest[0] = table[src[0]][dest[0]];
258                     dest[1] = table[src[1]][dest[1]];
259                     dest[3] = table[src[2]][dest[2]];
260                     dest[2] = 0xff;
261                 }
262                 break;
263             case 1:
264                 for (; src < srcend; src += 4, dest += 4) {
265                     dest[0] = table[src[0]][dest[0]];
266                     dest[2] = table[src[1]][dest[1]];
267                     dest[3] = table[src[2]][dest[2]];
268                     dest[1] = 0xff;
269                 }
270                 break;
271             case 0:
272                 for (; src < srcend; src += 4, dest += 4) {
273                     dest[1] = table[src[1]][dest[1]];
274                     dest[2] = table[src[2]][dest[2]];
275                     dest[3] = table[src[3]][dest[3]];
276                     dest[0] = 0xff;
277                 }
278                 break;
279             default:
280                 for (; src < srcend; src += 4, dest += 4) {
281                     dest[1] = table[src[1]][dest[1]];
282                     dest[2] = table[src[2]][dest[2]];
283                     dest[3] = table[src[3]][dest[3]];
284                     dest[4] = table[src[4]][dest[4]];
285                 }
286         }
287     }
288 }
289 
doit(struct filter * f,int flags,int time1)290 static int doit(struct filter *f, int flags, int time1)
291 {
292     int val, n;
293     int time = time1;
294     struct blurdata *s = (struct blurdata *)f->data;
295     updateinheredimage(f);
296     val = f->previous->action->doit(f->previous, flags, time);
297     s->counter += time;
298     if (val & CHANGED)
299         s->counter = 0;
300     n = (int)((1 - pow(1.0 - AMOUNT, (time + s->bckuptime) / DIV)) * 256);
301     if (s->counter >= 2 * MAXFRAMES) {
302         return val;
303     }
304     if (n < 10) {
305         s->bckuptime += time;
306         return val | ANIMATION;
307     }
308     s->bckuptime = 0;
309     if (s->counter >= MAXFRAMES)
310         n = 256, s->counter = 2 * MAXFRAMES;
311     if (s->n != n) {
312         s->n = n;
313         switch (f->image->bytesperpixel) {
314             case 1:
315                 if (s->table == NULL)
316                     s->table = (unsigned char(*)[256])malloc(256 * 256);
317                 blur8(f);
318                 break;
319             case 3:
320             case 4:
321                 if (s->table == NULL)
322                     s->table = (unsigned char(*)[256])malloc(256 * 256);
323                 blurtruecolor(f);
324                 break;
325             default:
326                 if (s->table != NULL)
327                     free(s->table), s->table = NULL;
328         }
329     }
330     switch (f->image->palette->type) {
331         case C256:
332         case GRAYSCALE:
333             xth_function(blur82, f, f->image->height);
334             break;
335 #ifdef SUPPORT16
336         case TRUECOLOR16:
337             xth_function(blur16, f, f->image->height);
338             break;
339 #endif
340         case TRUECOLOR:
341             xth_function(blur32, f, f->image->height);
342             break;
343 #ifdef STRUECOLOR24
344         case TRUECOLOR24:
345             xth_function(blur24, f, f->image->height);
346             break;
347 #endif
348     }
349     xth_sync();
350     if (s->counter == 2 * MAXFRAMES) {
351         return val | CHANGED;
352     }
353     return val | CHANGED | ANIMATION;
354 }
355 
myremovefilter(struct filter * f)356 static void myremovefilter(struct filter *f)
357 {
358     struct blurdata *s = (struct blurdata *)f->data;
359     if (s->savedpalette != NULL) {
360         restorepalette(f->image->palette, s->savedpalette);
361         destroypalette(s->savedpalette);
362         s->savedpalette = NULL;
363     }
364 }
365 
366 const struct filteraction blur_filter = {
367     "Motionblur",       "blur",          0,
368     getinstance,        destroyinstance, doit,
369     requirement,        initialize,      convertupgeneric,
370     convertdowngeneric, myremovefilter};
371