1 /* filter.c version 0.7
2 * contient les filtres applicable a un buffer
3 * creation : 01/10/2000
4 * -ajout de sinFilter()
5 * -ajout de zoomFilter()
6 * -copie de zoomFilter() en zoomFilterRGB(), gérant les 3 couleurs
7 * -optimisation de sinFilter (utilisant une table de sin)
9 * -optimisation de la procedure de génération du buffer de transformation
10 * la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
13 /*#define _DEBUG_PIXEL; */
21 #include "goom_tools.h"
22 #include "goom_core.h"
35 #define EFFECT_DISTORS 4
37 #define EFFECT_DISTORS 10
45 guint32 mmx_zoom_size;
49 extern unsigned int useAltivec;
50 extern void ppc_zoom (void);
51 extern void ppc_zoom_altivec (void);
52 unsigned int ppcsize4;
56 unsigned int *coeffs = 0, *freecoeffs = 0;
57 guint32 *expix1 = 0; /* pointeur exporte vers p1 */
58 guint32 *expix2 = 0; /* pointeur exporte vers p2 */
63 static int firstTime = 1;
64 static int sintable[0xffff];
69 ZoomFilterData *zf = malloc (sizeof (ZoomFilterData));
94 /* retourne x>>s , en testant le signe de x */
96 ShiftRight (int x, const unsigned char s)
105 calculer px et py en fonction de x,y,middleX,middleY et theMode
106 px et py indique la nouvelle position (en sqrtperte ieme de pixel)
110 calculatePXandPY (GoomData * gd, int x, int y, int *px, int *py)
112 ZoomFilterData *zf = gd->zfd;
113 int middleX, middleY;
114 guint32 resoly = zf->res_y;
115 int vPlaneEffect = zf->vPlaneEffect;
116 int hPlaneEffect = zf->hPlaneEffect;
117 int vitesse = zf->vitesse;
118 char theMode = zf->mode;
120 if (theMode == WATER_MODE) {
121 int wavesp = zf->wavesp;
123 int yy = y + RAND (gd) % 4 + wave / 10;
131 *px = (x << 4) + zf->firedec[yy] + (wave / 10);
132 *py = (y << 4) + 132 - ((vitesse < 132) ? vitesse : 131);
134 wavesp += RAND (gd) % 3;
135 wavesp -= RAND (gd) % 3;
140 wave += (wavesp / 10) + RAND (gd) % 3;
141 wave -= RAND (gd) % 3;
143 wavesp = (wavesp * 9) / 10;
150 int fvitesse = vitesse << 4;
152 middleX = zf->middleX;
153 middleY = zf->middleY;
156 x += RAND (gd) % zf->noisify;
157 x -= RAND (gd) % zf->noisify;
158 y += RAND (gd) % zf->noisify;
159 y -= RAND (gd) % zf->noisify;
163 vx = ((x - middleX) << 9) + hPlaneEffect * (y - middleY);
165 vx = (x - middleX) << 9;
168 vy = ((y - middleY) << 9) + vPlaneEffect * (x - middleX);
170 vy = (y - middleY) << 9;
175 ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
176 9) * ShiftRight (vy, 9);
179 ShiftRight (sintable[(unsigned short) (0xffff * dist *
180 EFFECT_DISTORS)], 6);
183 case CRYSTAL_BALL_MODE:
185 ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
186 9) * ShiftRight (vy, 9);
187 fvitesse += (dist * EFFECT_DISTORS >> 10);
191 ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
192 9) * ShiftRight (vy, 9);
193 fvitesse -= (dist * EFFECT_DISTORS >> 4);
197 ShiftRight (vx, 9) * ShiftRight (vx, 9) + ShiftRight (vy,
198 9) * ShiftRight (vy, 9);
199 fvitesse -= (dist * EFFECT_DISTORS >> 9);
203 *px = (middleX << 4) - (-(vx * fvitesse) >> 16);
205 *px = (middleX << 4) + ((vx * fvitesse) >> 16);
207 *py = (middleY << 4) - (-(vy * fvitesse) >> 16);
209 *py = (middleY << 4) + ((vy * fvitesse) >> 16);
216 setPixelRGB (Uint * buffer, Uint x, Uint y, Color c,
217 guint32 resolx, guint32 resoly)
219 /* buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b */
221 if (x + y * resolx >= resolx * resoly) {
222 fprintf (stderr, "setPixel ERROR : hors du tableau... %i, %i\n", x, y);
228 buffer[y * resolx + x] = (c.b << 16) | (c.v << 8) | c.r;
230 buffer[y * resolx + x] = (c.r << 16) | (c.v << 8) | c.b;
236 setPixelRGB_ (Uint * buffer, Uint x, Color c, guint32 resolx, guint32 resoly)
239 if (x >= resolx * resoly) {
240 printf ("setPixel ERROR : hors du tableau... %i >= %i*%i (%i)\n", x, resolx,
241 resoly, resolx * resoly);
247 buffer[x] = (c.b << 16) | (c.v << 8) | c.r;
249 buffer[x] = (c.r << 16) | (c.v << 8) | c.b;
254 getPixelRGB_ (Uint * buffer, Uint x, Color * c, guint32 resolx, guint32 resoly)
256 register unsigned char *tmp8;
259 if (x >= resolx * resoly) {
260 printf ("getPixel ERROR : hors du tableau... %i\n", x);
265 #ifdef __BIG_ENDIAN__
266 c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
267 c->r = *(unsigned char *) (++tmp8);
268 c->v = *(unsigned char *) (++tmp8);
269 c->b = *(unsigned char *) (++tmp8);
272 /* ATTENTION AU PETIT INDIEN */
273 tmp8 = (unsigned char *) (buffer + x);
274 c->b = *(unsigned char *) (tmp8++);
275 c->v = *(unsigned char *) (tmp8++);
276 c->r = *(unsigned char *) (tmp8);
277 /* *c = (Color) buffer[x+y*WIDTH] ; */
282 zoomFilterSetResolution (GoomData * gd, ZoomFilterData * zf)
286 if (zf->buffsize >= gd->buffsize) {
287 zf->res_x = gd->resolx;
288 zf->res_y = gd->resoly;
289 zf->middleX = gd->resolx / 2;
290 zf->middleY = gd->resoly - 1;
303 zf->middleX = gd->resolx / 2;
304 zf->middleY = gd->resoly - 1;
305 zf->res_x = gd->resolx;
306 zf->res_y = gd->resoly;
312 zf->buffsize = gd->resolx * gd->resoly * sizeof (unsigned int);
315 freecoeffs = (unsigned int *)
316 malloc (resx * resy * 2 * sizeof (unsigned int) + 128);
317 coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128);
320 zf->buffer = calloc (sizeof (guint32), zf->buffsize * 5);
321 zf->pos10 = zf->buffer;
322 zf->c[0] = zf->pos10 + zf->buffsize;
323 zf->c[1] = zf->c[0] + zf->buffsize;
324 zf->c[2] = zf->c[1] + zf->buffsize;
325 zf->c[3] = zf->c[2] + zf->buffsize;
327 zf->firedec = (int *) malloc (zf->res_y * sizeof (int));
332 /* generation d'une table de sinus */
333 for (us = 0; us < 0xffff; us++) {
334 sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff));
340 zoomFilterDestroy (ZoomFilterData * zf)
351 /*===============================================================*/
353 zoomFilterFastRGB (GoomData * goomdata, ZoomFilterData * zf, int zfd_update)
355 guint32 prevX = goomdata->resolx;
356 guint32 prevY = goomdata->resoly;
358 guint32 *pix1 = goomdata->p1;
359 guint32 *pix2 = goomdata->p2;
365 /* static unsigned int prevX = 0, prevY = 0; */
372 Color col1, col2, col3, col4;
376 if ((goomdata->resolx != zf->res_x) || (goomdata->resoly != zf->res_y)) {
377 zoomFilterSetResolution (goomdata, zf);
384 guchar sqrtperte = zf->sqrtperte;
388 zf->vitesse = 256 - zf->vitesse;
390 /* generation du buffer */
391 for (y = 0; y < zf->res_y; y++) {
393 gint max_px = (prevX - 1) * sqrtperte;
394 gint max_py = (prevY - 1) * sqrtperte;
396 for (x = 0; x < zf->res_x; x++) {
400 /* calculer px et py en fonction de */
401 /* x,y,middleX,middleY et theMode */
402 calculatePXandPY (goomdata, x, y, &px, &py);
404 if ((px == x << 4) && (py == y_16))
407 if ((py < 0) || (px < 0) || (py >= max_py) || (px >= max_px)) {
409 coeffs[(y * prevX + x) * 2] = 0;
410 coeffs[(y * prevX + x) * 2 + 1] = 0;
412 pos10[start_y + x] = 0;
413 c[0][start_y + x] = 0;
414 c[1][start_y + x] = 0;
415 c[2][start_y + x] = 0;
416 c[3][start_y + x] = 0;
423 npx10 = (px / sqrtperte);
424 npy10 = (py / sqrtperte);
426 /* if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10);
427 if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10);
429 coefh = px % sqrtperte;
430 coefv = py % sqrtperte;
432 pos = (y * prevX + x) * 2;
433 coeffs[pos] = (npx10 + prevX * npy10) * 4;
435 if (!(coefh || coefv))
436 coeffs[pos + 1] = (sqrtperte * sqrtperte - 1);
438 coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv));
440 coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8;
441 coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16;
442 coeffs[pos + 1] |= (coefh * coefv) << 24;
445 pos10[pos] = npx10 + prevX * npy10;
447 if (!(coefh || coefv))
448 c[0][pos] = sqrtperte * sqrtperte - 1;
450 c[0][pos] = (sqrtperte - coefh) * (sqrtperte - coefv);
452 c[1][pos] = coefh * (sqrtperte - coefv);
453 c[2][pos] = (sqrtperte - coefh) * coefv;
454 c[3][pos] = coefh * coefv;
458 /* Advance start of line index */
465 mmx_zoom_size = prevX * prevY;
472 ppcsize4 = ((unsigned int) (prevX * prevY)) / 4;
475 ppcsize4 = ((unsigned int) (prevX * prevY));
480 for (position = 0; position < prevX * prevY; position++) {
481 getPixelRGB_ (pix1, pos10[position], &col1, goomdata->resolx,
483 getPixelRGB_ (pix1, pos10[position] + 1, &col2, goomdata->resolx,
485 getPixelRGB_ (pix1, pos10[position] + prevX, &col3, goomdata->resolx,
487 getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4, goomdata->resolx,
490 couleur.r = col1.r * c[0][position]
491 + col2.r * c[1][position]
492 + col3.r * c[2][position]
493 + col4.r * c[3][position];
494 couleur.r >>= zf->pertedec;
496 couleur.v = col1.v * c[0][position]
497 + col2.v * c[1][position]
498 + col3.v * c[2][position]
499 + col4.v * c[3][position];
500 couleur.v >>= zf->pertedec;
502 couleur.b = col1.b * c[0][position]
503 + col2.b * c[1][position]
504 + col3.b * c[2][position]
505 + col4.b * c[3][position];
506 couleur.b >>= zf->pertedec;
508 setPixelRGB_ (pix2, position, couleur, goomdata->resolx, goomdata->resoly);
515 pointFilter (GoomData * goomdata, Color c,
516 float t1, float t2, float t3, float t4, Uint cycle)
518 Uint *pix1 = goomdata->p1;
519 ZoomFilterData *zf = goomdata->zfd;
520 Uint x = (Uint) (zf->middleX + (int) (t1 * cos ((float) cycle / t3)));
521 Uint y = (Uint) (zf->middleY + (int) (t2 * sin ((float) cycle / t4)));
523 if ((x > 1) && (y > 1) && (x < goomdata->resolx - 2)
524 && (y < goomdata->resoly - 2)) {
525 setPixelRGB (pix1, x + 1, y, c, goomdata->resolx, goomdata->resoly);
526 setPixelRGB (pix1, x, y + 1, c, goomdata->resolx, goomdata->resoly);
527 setPixelRGB (pix1, x + 1, y + 1, WHITE, goomdata->resolx, goomdata->resoly);
528 setPixelRGB (pix1, x + 2, y + 1, c, goomdata->resolx, goomdata->resoly);
529 setPixelRGB (pix1, x + 1, y + 2, c, goomdata->resolx, goomdata->resoly);