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