gst/goom/: Add license headers in all source files. Remove filter.c from
[platform/upstream/gst-plugins-good.git] / gst / goom / filters.c
1 /* Goom Project
2  * Copyright (C) <2003> iOS-Software
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 // --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY ---
20
21 /* filter.c version 0.7
22 * contient les filtres applicable a un buffer
23 * creation : 01/10/2000
24 *  -ajout de sinFilter()
25 *  -ajout de zoomFilter()
26 *  -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs
27 *  -optimisation de sinFilter (utilisant une table de sin)
28 *       -asm
29 *       -optimisation de la procedure de generation du buffer de transformation
30 *               la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
31 */
32
33 /* #define _DEBUG_PIXEL */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <string.h>
40 #include <stdlib.h>
41 #include <math.h>
42 #include <stdio.h>
43
44 #ifdef HAVE_INTTYPES_H
45 #include <inttypes.h>
46 #endif
47
48 #include "goom_filters.h"
49 #include "goom_graphic.h"
50 #include "goom_tools.h"
51 #include "goom_plugin_info.h"
52 #include "goom_fx.h"
53 #include "v3d.h"
54
55 /* TODO : MOVE THIS AWAY !!! */
56 /* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */
57 static inline void
58 setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c)
59 {
60   Pixel i;
61
62   i.channels.b = c.b;
63   i.channels.g = c.v;
64   i.channels.r = c.r;
65   *(buffer + (x + y * goomInfo->screen.width)) = i;
66 }
67
68 static inline void
69 setPixelRGB_ (Pixel * buffer, Uint x, Color c)
70 {
71   buffer[x].channels.r = c.r;
72   buffer[x].channels.g = c.v;
73   buffer[x].channels.b = c.b;
74 }
75
76 static inline void
77 getPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color * c)
78 {
79   Pixel i = *(buffer + (x + y * goomInfo->screen.width));
80
81   c->b = i.channels.b;
82   c->v = i.channels.g;
83   c->r = i.channels.r;
84 }
85
86 static inline void
87 getPixelRGB_ (Pixel * buffer, Uint x, Color * c)
88 {
89   Pixel i = *(buffer + x);
90
91   c->b = i.channels.b;
92   c->v = i.channels.g;
93   c->r = i.channels.r;
94 }
95
96 /* END TODO */
97
98
99 /* DEPRECATED */
100 // retourne x>>s , en testant le signe de x
101 //#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s)))
102 //#define EFFECT_DISTORS 4
103 //#define EFFECT_DISTORS_SL 2
104 //#define INTERLACE_ADD 9
105 //#define INTERLACE_AND 0xf
106 /* END DEPRECATED */
107
108 #define BUFFPOINTNB 16
109 #define BUFFPOINTNBF 16.0f
110 #define BUFFPOINTMASK 0xffff
111
112 #define sqrtperte 16
113 /* faire : a % sqrtperte <=> a & pertemask */
114 #define PERTEMASK 0xf
115 /* faire : a / sqrtperte <=> a >> PERTEDEC */
116 #define PERTEDEC 4
117
118 /* pure c version of the zoom filter */
119 static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX,
120     unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio,
121     int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
122
123 /* simple wrapper to give it the same proto than the others */
124 void
125 zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS,
126     int *brutD, int buffratio, int precalCoef[16][16])
127 {
128   c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef);
129 }
130
131 static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
132
133
134 typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA
135 {
136
137   PluginParam enabled_bp;
138   PluginParameters params;
139
140   unsigned int *coeffs, *freecoeffs;
141
142   signed int *brutS, *freebrutS;        /* source */
143   signed int *brutD, *freebrutD;        /* dest */
144   signed int *brutT, *freebrutT;        /* temp (en cours de generation) */
145
146   guint32 zoom_width;
147
148   unsigned int prevX, prevY;
149
150   float general_speed;
151   int reverse;                  /* reverse the speed */
152   char theMode;
153   int waveEffect;
154   int hypercosEffect;
155   int vPlaneEffect;
156   int hPlaneEffect;
157   char noisify;
158   int middleX, middleY;
159
160   int mustInitBuffers;
161   int interlace_start;
162
163     /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
164   int buffratio;
165   int *firedec;
166
167     /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
168   int precalCoef[BUFFPOINTNB][BUFFPOINTNB];
169
170     /** calculatePXandPY statics */
171   int wave;
172   int wavesp;
173
174 } ZoomFilterFXWrapperData;
175
176
177
178
179 static inline v2g
180 zoomVector (ZoomFilterFXWrapperData * data, float X, float Y)
181 {
182   v2g vecteur;
183   float vx, vy;
184   float sq_dist = X * X + Y * Y;
185
186   /*    sx = (X < 0.0f) ? -1.0f : 1.0f;
187      sy = (Y < 0.0f) ? -1.0f : 1.0f;
188    */
189   float coefVitesse = (1.0f + data->general_speed) / 50.0f;
190
191   // Effects
192
193   /* Centralized FX */
194
195   switch (data->theMode) {
196     case CRYSTAL_BALL_MODE:
197       coefVitesse -= (sq_dist - 0.3f) / 15.0f;
198       break;
199     case AMULETTE_MODE:
200       coefVitesse += sq_dist * 3.5f;
201       break;
202     case WAVE_MODE:
203       coefVitesse += sin (sq_dist * 20.0f) / 100.0f;
204       break;
205     case SCRUNCH_MODE:
206       coefVitesse += sq_dist / 10.0f;
207       break;
208       //case HYPERCOS1_MODE:
209       break;
210       //case HYPERCOS2_MODE:
211       break;
212       //case YONLY_MODE:
213       break;
214     case SPEEDWAY_MODE:
215       coefVitesse *= 4.0f * Y;
216       break;
217     default:
218       break;
219   }
220
221   if (coefVitesse < -2.01f)
222     coefVitesse = -2.01f;
223   if (coefVitesse > 2.01f)
224     coefVitesse = 2.01f;
225
226   vx = coefVitesse * X;
227   vy = coefVitesse * Y;
228
229   /* Amulette 2 */
230   // vx = X * tan(dist);
231   // vy = Y * tan(dist);
232
233   /* Rotate */
234   //vx = (X+Y)*0.1;
235   //vy = (Y-X)*0.1;
236
237
238   // Effects adds-on
239
240   /* Noise */
241   if (data->noisify) {
242     vx += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
243     vy += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f;
244   }
245
246   /* Hypercos */
247   if (data->hypercosEffect) {
248     vx += sin (Y * 10.0f) / 120.0f;
249     vy += sin (X * 10.0f) / 120.0f;
250   }
251
252   /* H Plane */
253   if (data->hPlaneEffect)
254     vx += Y * 0.0025f * data->hPlaneEffect;
255
256   /* V Plane */
257   if (data->vPlaneEffect)
258     vy += X * 0.0025f * data->vPlaneEffect;
259
260   /* TODO : Water Mode */
261   //    if (data->waveEffect)
262
263   vecteur.x = vx;
264   vecteur.y = vy;
265
266   return vecteur;
267 }
268
269
270 /*
271  * Makes a stripe of a transform buffer (brutT)
272  *
273  * The transform is (in order) :
274  * Translation (-data->middleX, -data->middleY)
275  * Homothetie (Center : 0,0   Coeff : 2/data->prevX)
276  */
277 static void
278 makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR)
279 {
280   // Position of the pixel to compute in pixmap coordinates
281   Uint x, y;
282
283   // Where (verticaly) to stop generating the buffer stripe
284   int maxEnd = (data->interlace_start + INTERLACE_INCR);
285
286   // Ratio from pixmap to normalized coordinates
287   float ratio = 2.0f / ((float) data->prevX);
288
289   // Ratio from normalized to virtual pixmap coordinates
290   float inv_ratio = BUFFPOINTNBF / ratio;
291   float min = ratio / BUFFPOINTNBF;
292
293   // Y position of the pixel to compute in normalized coordinates
294   float Y = ((float) (data->interlace_start - data->middleY)) * ratio;
295
296   maxEnd = data->prevY;
297   if (maxEnd > (data->interlace_start + INTERLACE_INCR))
298     maxEnd = (data->interlace_start + INTERLACE_INCR);
299
300   for (y = data->interlace_start;
301       (y < data->prevY) && ((signed int) y < maxEnd); y++) {
302     Uint premul_y_prevX = y * data->prevX * 2;
303     float X = -((float) data->middleX) * ratio;
304
305     for (x = 0; x < data->prevX; x++) {
306       v2g vector = zoomVector (data, X, Y);
307
308       /* Finish and avoid null displacement */
309       if (fabs (vector.x) < min)
310         vector.x = (vector.x < 0.0f) ? -min : min;
311       if (fabs (vector.y) < min)
312         vector.y = (vector.y < 0.0f) ? -min : min;
313
314       data->brutT[premul_y_prevX] =
315           ((int) ((X - vector.x) * inv_ratio) +
316           ((int) (data->middleX * BUFFPOINTNB)));
317       data->brutT[premul_y_prevX + 1] =
318           ((int) ((Y - vector.y) * inv_ratio) +
319           ((int) (data->middleY * BUFFPOINTNB)));
320       premul_y_prevX += 2;
321       X += ratio;
322     }
323     Y += ratio;
324   }
325   data->interlace_start += INTERLACE_INCR;
326   if (y >= data->prevY - 1)
327     data->interlace_start = -1;
328 }
329
330
331 /*
332  * calculer px et py en fonction de x,y,middleX,middleY et theMode
333  * px et py indique la nouvelle position (en sqrtperte ieme de pixel)
334  * (valeur * 16)
335  
336  inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py)
337  {
338      if (data->theMode == WATER_MODE) {
339          int yy;
340          
341          yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10;
342          if (yy < 0)
343              yy = 0;
344          if (yy >= (signed int)goomInfo->screen.height)
345              yy = goomInfo->screen.height - 1;
346          
347          *px = (x << 4) + data->firedec[yy] + (data->wave / 10);
348          *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130);
349          
350          data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
351          if (data->wave < -10)
352              data->wavesp += 2;
353          if (data->wave > 10)
354              data->wavesp -= 2;
355          data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
356          if (data->wavesp > 100)
357              data->wavesp = (data->wavesp * 9) / 10;
358      }
359      else {
360          int     dist = 0, vx9, vy9;
361          int     vx, vy;
362          int     ppx, ppy;
363          int     fvitesse = data->vitesse << 4;
364          
365          if (data->noisify) {
366              x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
367              y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
368          }
369          vx = (x - data->middleX) << 9;
370          vy = (y - data->middleY) << 9;
371          
372          if (data->hPlaneEffect)
373              vx += data->hPlaneEffect * (y - data->middleY);
374          
375          if (data->vPlaneEffect)
376              vy += data->vPlaneEffect * (x - data->middleX);
377          
378          if (data->waveEffect) {
379              fvitesse *=
380              1024 +
381              ShiftRight (goomInfo->sintable
382                          [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6);
383              fvitesse /= 1024;
384          }
385          
386          if (data->hypercosEffect) {
387              vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
388              vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
389          }
390          
391          vx9 = ShiftRight (vx, 9);
392          vy9 = ShiftRight (vy, 9);
393          dist = vx9 * vx9 + vy9 * vy9;
394          
395          switch (data->theMode) {
396              case WAVE_MODE:
397                  fvitesse *=
398                  1024 +
399                  ShiftRight (goomInfo->sintable
400                              [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6);
401                  fvitesse>>=10;
402                  break;
403              case CRYSTAL_BALL_MODE:
404                  fvitesse += (dist >> (10-EFFECT_DISTORS_SL));
405                  break;
406              case AMULETTE_MODE:
407                  fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL));
408                  break;
409              case SCRUNCH_MODE:
410                  fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL));
411                  break;
412              case HYPERCOS1_MODE:
413                  vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
414                  vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
415                  break;
416              case HYPERCOS2_MODE:
417                  vx =
418                  vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0);
419                  vy =
420                      vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0);
421                  fvitesse = 128 << 4;
422                  break;
423              case YONLY_MODE:
424                  fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6);
425                  fvitesse >>= 10;
426                  break;
427              case SPEEDWAY_MODE:
428                  fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL));
429                  break;
430          }
431          
432          if (fvitesse < -3024)
433              fvitesse = -3024;
434          
435          if (vx < 0)                                                                    // pb avec decalage sur nb negatif
436              ppx = -(-(vx * fvitesse) >> 16);
437          // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile)
438          //    * * * * * 9 = nb chiffre virgule de vx) 
439          else
440              ppx = ((vx * fvitesse) >> 16);
441          
442          if (vy < 0)
443              ppy = -(-(vy * fvitesse) >> 16);
444          else
445              ppy = ((vy * fvitesse) >> 16);
446          
447          *px = (data->middleX << 4) + ppx;
448          *py = (data->middleY << 4) + ppy;
449      }
450  }
451  */
452
453
454
455 static void
456 c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, unsigned int prevY,
457     signed int *brutS, signed int *brutD, int buffratio, int precalCoef[16][16])
458 {
459   int myPos, myPos2;
460   Color couleur;
461
462   unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
463
464   int bufsize = prevX * prevY * 2;
465   int bufwidth = prevX;
466
467   expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val =
468       expix1[prevX * prevY - prevX].val = 0;
469
470   for (myPos = 0; myPos < bufsize; myPos += 2) {
471     Color col1, col2, col3, col4;
472     int c1, c2, c3, c4, px, py;
473     int pos;
474     int coeffs;
475
476     int brutSmypos = brutS[myPos];
477
478     myPos2 = myPos + 1;
479
480     px = brutSmypos + (((brutD[myPos] -
481                 brutSmypos) * buffratio) >> BUFFPOINTNB);
482     brutSmypos = brutS[myPos2];
483     py = brutSmypos + (((brutD[myPos2] -
484                 brutSmypos) * buffratio) >> BUFFPOINTNB);
485
486     if ((py >= ay) || (px >= ax)) {
487       pos = coeffs = 0;
488     } else {
489       pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
490       /* coef en modulo 15 */
491       coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
492     }
493     getPixelRGB_ (expix1, pos, &col1);
494     getPixelRGB_ (expix1, pos + 1, &col2);
495     getPixelRGB_ (expix1, pos + bufwidth, &col3);
496     getPixelRGB_ (expix1, pos + bufwidth + 1, &col4);
497
498     c1 = coeffs;
499     c2 = (c1 >> 8) & 0xFF;
500     c3 = (c1 >> 16) & 0xFF;
501     c4 = (c1 >> 24) & 0xFF;
502     c1 = c1 & 0xff;
503
504     couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4;
505     if (couleur.r > 5)
506       couleur.r -= 5;
507     couleur.r >>= 8;
508
509     couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4;
510     if (couleur.v > 5)
511       couleur.v -= 5;
512     couleur.v >>= 8;
513
514     couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4;
515     if (couleur.b > 5)
516       couleur.b -= 5;
517     couleur.b >>= 8;
518
519     setPixelRGB_ (expix2, myPos >> 1, couleur);
520   }
521 }
522
523 /** generate the water fx horizontal direction buffer */
524 static void
525 generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo,
526     ZoomFilterFXWrapperData * data)
527 {
528
529   int loopv;
530   int decc = goom_irand (goomInfo->gRandom, 8) - 4;
531   int spdc = goom_irand (goomInfo->gRandom, 8) - 4;
532   int accel = goom_irand (goomInfo->gRandom, 8) - 4;
533
534   for (loopv = data->prevY; loopv != 0;) {
535
536     loopv--;
537     data->firedec[loopv] = decc;
538     decc += spdc / 10;
539     spdc +=
540         goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3);
541
542     if (decc > 4)
543       spdc -= 1;
544     if (decc < -4)
545       spdc += 1;
546
547     if (spdc > 30)
548       spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10;
549     if (spdc < -30)
550       spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10;
551
552     if (decc > 8 && spdc > 1)
553       spdc -= goom_irand (goomInfo->gRandom, 3) - 2;
554
555     if (decc < -8 && spdc < -1)
556       spdc += goom_irand (goomInfo->gRandom, 3) + 2;
557
558     if (decc > 8 || decc < -8)
559       decc = decc * 8 / 9;
560
561     accel +=
562         goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2);
563     if (accel > 20)
564       accel -= 2;
565     if (accel < -20)
566       accel += 2;
567   }
568 }
569
570
571
572 /**
573 * Main work for the dynamic displacement map.
574  * 
575  * Reads data from pix1, write to pix2.
576  *
577  * Useful datas for this FX are stored in ZoomFilterData.
578  * 
579  * If you think that this is a strange function name, let me say that a long time ago,
580  *  there has been a slow version and a gray-level only one. Then came these function,
581  *  fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image.
582  *  So that is why you have this name, for the nostalgy of the first days of goom
583  *  when it was just a tiny program writen in Turbo Pascal on my i486...
584  */
585 void
586 zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2,
587     ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult)
588 {
589   Uint x, y;
590
591   ZoomFilterFXWrapperData *data =
592       (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data;
593
594   if (!BVAL (data->enabled_bp))
595     return;
596
597     /** changement de taille **/
598   if ((data->prevX != resx) || (data->prevY != resy)) {
599     data->prevX = resx;
600     data->prevY = resy;
601
602     if (data->brutS)
603       free (data->freebrutS);
604     data->brutS = 0;
605     if (data->brutD)
606       free (data->freebrutD);
607     data->brutD = 0;
608     if (data->brutT)
609       free (data->freebrutT);
610     data->brutT = 0;
611
612     data->middleX = resx / 2;
613     data->middleY = resy / 2;
614     data->mustInitBuffers = 1;
615     if (data->firedec)
616       free (data->firedec);
617     data->firedec = 0;
618   }
619
620   if (data->interlace_start != -2)
621     zf = NULL;
622
623     /** changement de config **/
624   if (zf) {
625     data->reverse = zf->reverse;
626     data->general_speed = (float) (zf->vitesse - 128) / 128.0f;
627     if (data->reverse)
628       data->general_speed = -data->general_speed;
629     data->middleX = zf->middleX;
630     data->middleY = zf->middleY;
631     data->theMode = zf->mode;
632     data->hPlaneEffect = zf->hPlaneEffect;
633     data->vPlaneEffect = zf->vPlaneEffect;
634     data->waveEffect = zf->waveEffect;
635     data->hypercosEffect = zf->hypercosEffect;
636     data->noisify = zf->noisify;
637     data->interlace_start = 0;
638   }
639
640
641   if (data->mustInitBuffers) {
642
643     data->mustInitBuffers = 0;
644     data->freebrutS =
645         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
646     data->brutS =
647         (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128);
648
649     data->freebrutD =
650         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
651     data->brutD =
652         (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128);
653
654     data->freebrutT =
655         (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int));
656     data->brutT =
657         (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128);
658
659     data->buffratio = 0;
660
661     data->firedec = (int *) malloc (data->prevY * sizeof (int));
662     generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data);
663
664     data->interlace_start = 0;
665     makeZoomBufferStripe (data, resy);
666
667     /* Copy the data from temp to dest and source */
668     memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int));
669     memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int));
670   }
671
672   /* generation du buffer de trans */
673   if (data->interlace_start == -1) {
674
675     /* sauvegarde de l'etat actuel dans la nouvelle source
676      * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */
677     y = data->prevX * data->prevY * 2;
678     for (x = 0; x < y; x += 2) {
679       int brutSmypos = data->brutS[x];
680       int x2 = x + 1;
681
682       data->brutS[x] =
683           brutSmypos + (((data->brutD[x] -
684                   brutSmypos) * data->buffratio) >> BUFFPOINTNB);
685       brutSmypos = data->brutS[x2];
686       data->brutS[x2] =
687           brutSmypos + (((data->brutD[x2] -
688                   brutSmypos) * data->buffratio) >> BUFFPOINTNB);
689     }
690     data->buffratio = 0;
691   }
692
693   if (data->interlace_start == -1) {
694     signed int *tmp;
695
696     tmp = data->brutD;
697     data->brutD = data->brutT;
698     data->brutT = tmp;
699     tmp = data->freebrutD;
700     data->freebrutD = data->freebrutT;
701     data->freebrutT = tmp;
702     data->interlace_start = -2;
703   }
704
705   if (data->interlace_start >= 0) {
706     /* creation de la nouvelle destination */
707     makeZoomBufferStripe (data, resy / 16);
708   }
709
710   if (switchIncr != 0) {
711     data->buffratio += switchIncr;
712     if (data->buffratio > BUFFPOINTMASK)
713       data->buffratio = BUFFPOINTMASK;
714   }
715
716   if (switchMult != 1.0f) {
717     data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) +
718         (float) data->buffratio * switchMult);
719   }
720
721   data->zoom_width = data->prevX;
722
723   goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2,
724       data->brutS, data->brutD, data->buffratio, data->precalCoef);
725 }
726
727 static void
728 generatePrecalCoef (int precalCoef[16][16])
729 {
730   int coefh, coefv;
731
732   for (coefh = 0; coefh < 16; coefh++) {
733     for (coefv = 0; coefv < 16; coefv++) {
734
735       int i;
736       int diffcoeffh;
737       int diffcoeffv;
738
739       diffcoeffh = sqrtperte - coefh;
740       diffcoeffv = sqrtperte - coefv;
741
742       if (!(coefh || coefv)) {
743         i = 255;
744       } else {
745         int i1, i2, i3, i4;
746
747         i1 = diffcoeffh * diffcoeffv;
748         i2 = coefh * diffcoeffv;
749         i3 = diffcoeffh * coefv;
750         i4 = coefh * coefv;
751
752         // TODO: faire mieux...
753         if (i1)
754           i1--;
755         if (i2)
756           i2--;
757         if (i3)
758           i3--;
759         if (i4)
760           i4--;
761
762         i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24);
763       }
764       precalCoef[coefh][coefv] = i;
765     }
766   }
767 }
768
769 /* VisualFX Wrapper */
770
771 static void
772 zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info)
773 {
774   ZoomFilterFXWrapperData *data =
775       (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData));
776
777   data->coeffs = 0;
778   data->freecoeffs = 0;
779   data->brutS = 0;
780   data->freebrutS = 0;
781   data->brutD = 0;
782   data->freebrutD = 0;
783   data->brutT = 0;
784   data->freebrutT = 0;
785   data->prevX = 0;
786   data->prevY = 0;
787
788   data->mustInitBuffers = 1;
789   data->interlace_start = -2;
790
791   data->general_speed = 0.0f;
792   data->reverse = 0;
793   data->theMode = AMULETTE_MODE;
794   data->waveEffect = 0;
795   data->hypercosEffect = 0;
796   data->vPlaneEffect = 0;
797   data->hPlaneEffect = 0;
798   data->noisify = 2;
799
800     /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
801   data->buffratio = 0;
802   data->firedec = 0;
803
804   data->wave = data->wavesp = 0;
805
806   data->enabled_bp = secure_b_param ("Enabled", 1);
807
808   data->params = plugin_parameters ("Zoom Filter", 1);
809   data->params.params[0] = &data->enabled_bp;
810
811   _this->params = &data->params;
812   _this->fx_data = (void *) data;
813
814     /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
815   generatePrecalCoef (data->precalCoef);
816 }
817
818 static void
819 zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this)
820 {
821   ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) _this->fx_data;
822
823   if (data->freebrutT)
824     free (data->freebrutT);
825   if (data->freebrutS)
826     free (data->freebrutS);
827   if (data->freebrutD)
828     free (data->freebrutD);
829   if (data->firedec)
830     free (data->firedec);
831
832   goom_plugin_parameters_free (_this->params);
833
834   free (_this->fx_data);
835 }
836
837 static void
838 zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src,
839     Pixel * dest, PluginInfo * info)
840 {
841 }
842
843 VisualFX
844 zoomFilterVisualFXWrapper_create (void)
845 {
846   VisualFX fx;
847
848   fx.init = zoomFilterVisualFXWrapper_init;
849   fx.free = zoomFilterVisualFXWrapper_free;
850   fx.apply = zoomFilterVisualFXWrapper_apply;
851   fx.params = NULL;
852   fx.fx_data = NULL;
853   return fx;
854 }
855
856
857 /* TODO : MOVE THIS AWAY */
858
859 void
860 pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2,
861     float t3, float t4, Uint cycle)
862 {
863   Uint x = (Uint) ((int) (goomInfo->screen.width / 2)
864       + (int) (t1 * cos ((float) cycle / t3)));
865   Uint y = (Uint) ((int) (goomInfo->screen.height / 2)
866       + (int) (t2 * sin ((float) cycle / t4)));
867
868   if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2)
869       && (y < goomInfo->screen.height - 2)) {
870     setPixelRGB (goomInfo, pix1, x + 1, y, c);
871     setPixelRGB (goomInfo, pix1, x, y + 1, c);
872     setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE);
873     setPixelRGB (goomInfo, pix1, x + 2, y + 1, c);
874     setPixelRGB (goomInfo, pix1, x + 1, y + 2, c);
875   }
876 }