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;
256 getPixelRGB (Uint * buffer, Uint x, Uint y, Color * c,
257 guint32 resolx, guint32 resoly)
259 register unsigned char *tmp8;
262 if (x + y * resolx >= resolx * resoly) {
263 printf ("getPixel ERROR : hors du tableau... %i, %i\n", x, y);
268 #ifdef __BIG_ENDIAN__
269 c->b = *(unsigned char *) (tmp8 =
270 (unsigned char *) (buffer + (x + y * resolx)));
271 c->r = *(unsigned char *) (++tmp8);
272 c->v = *(unsigned char *) (++tmp8);
273 c->b = *(unsigned char *) (++tmp8);
276 /* ATTENTION AU PETIT INDIEN */
277 c->b = *(unsigned char *) (tmp8 =
278 (unsigned char *) (buffer + (x + y * resolx)));
279 c->v = *(unsigned char *) (++tmp8);
280 c->r = *(unsigned char *) (++tmp8);
281 /* *c = (Color) buffer[x+y*WIDTH] ; */
287 getPixelRGB_ (Uint * buffer, Uint x, Color * c, guint32 resolx, guint32 resoly)
289 register unsigned char *tmp8;
292 if (x >= resolx * resoly) {
293 printf ("getPixel ERROR : hors du tableau... %i\n", x);
298 #ifdef __BIG_ENDIAN__
299 c->b = *(unsigned char *) (tmp8 = (unsigned char *) (buffer + x));
300 c->r = *(unsigned char *) (++tmp8);
301 c->v = *(unsigned char *) (++tmp8);
302 c->b = *(unsigned char *) (++tmp8);
305 /* ATTENTION AU PETIT INDIEN */
306 tmp8 = (unsigned char *) (buffer + x);
307 c->b = *(unsigned char *) (tmp8++);
308 c->v = *(unsigned char *) (tmp8++);
309 c->r = *(unsigned char *) (tmp8);
310 /* *c = (Color) buffer[x+y*WIDTH] ; */
315 zoomFilterSetResolution (GoomData * gd, ZoomFilterData * zf)
319 if (zf->buffsize >= gd->buffsize) {
320 zf->res_x = gd->resolx;
321 zf->res_y = gd->resoly;
322 zf->middleX = gd->resolx / 2;
323 zf->middleY = gd->resoly - 1;
336 zf->middleX = gd->resolx / 2;
337 zf->middleY = gd->resoly - 1;
338 zf->res_x = gd->resolx;
339 zf->res_y = gd->resoly;
345 zf->buffsize = gd->resolx * gd->resoly * sizeof (unsigned int);
348 freecoeffs = (unsigned int *)
349 malloc (resx * resy * 2 * sizeof (unsigned int) + 128);
350 coeffs = (guint32 *) ((1 + ((unsigned int) (freecoeffs)) / 128) * 128);
353 zf->buffer = calloc (sizeof (guint32), zf->buffsize * 5);
354 zf->pos10 = zf->buffer;
355 zf->c[0] = zf->pos10 + zf->buffsize;
356 zf->c[1] = zf->c[0] + zf->buffsize;
357 zf->c[2] = zf->c[1] + zf->buffsize;
358 zf->c[3] = zf->c[2] + zf->buffsize;
360 zf->firedec = (int *) malloc (zf->res_y * sizeof (int));
365 /* generation d'une table de sinus */
366 for (us = 0; us < 0xffff; us++) {
367 sintable[us] = (int) (1024.0f * sin (us * 2 * 3.31415f / 0xffff));
374 for (loopv = zf->res_y; loopv != 0;) {
380 zf->firedec[loopv] = decc;
382 spdc += RAND (gd) % 3;
383 spdc -= RAND (gd) % 3;
391 spdc = spdc - RAND (gd) % 3 + accel / 10;
393 spdc = spdc + RAND (gd) % 3 + accel / 10;
395 if (decc > 8 && spdc > 1)
396 spdc -= RAND (gd) % 3 - 2;
398 if (decc < -8 && spdc < -1)
399 spdc += RAND (gd) % 3 + 2;
401 if (decc > 8 || decc < -8)
404 accel += RAND (gd) % 2;
405 accel -= RAND (gd) % 2;
415 zoomFilterDestroy (ZoomFilterData * zf)
426 /*===============================================================*/
428 zoomFilterFastRGB (GoomData * goomdata, ZoomFilterData * zf, int zfd_update)
430 guint32 prevX = goomdata->resolx;
431 guint32 prevY = goomdata->resoly;
433 guint32 *pix1 = goomdata->p1;
434 guint32 *pix2 = goomdata->p2;
440 /* static unsigned int prevX = 0, prevY = 0; */
447 Color col1, col2, col3, col4;
451 if ((goomdata->resolx != zf->res_x) || (goomdata->resoly != zf->res_y)) {
452 zoomFilterSetResolution (goomdata, zf);
459 guchar sqrtperte = zf->sqrtperte;
463 zf->vitesse = 256 - zf->vitesse;
465 /* generation du buffer */
466 for (y = 0; y < zf->res_y; y++) {
468 gint max_px = (prevX - 1) * sqrtperte;
469 gint max_py = (prevY - 1) * sqrtperte;
471 for (x = 0; x < zf->res_x; x++) {
475 /* calculer px et py en fonction de */
476 /* x,y,middleX,middleY et theMode */
477 calculatePXandPY (goomdata, x, y, &px, &py);
479 if ((px == x << 4) && (py == y_16))
482 if ((py < 0) || (px < 0) || (py >= max_py) || (px >= max_px)) {
484 coeffs[(y * prevX + x) * 2] = 0;
485 coeffs[(y * prevX + x) * 2 + 1] = 0;
487 pos10[start_y + x] = 0;
488 c[0][start_y + x] = 0;
489 c[1][start_y + x] = 0;
490 c[2][start_y + x] = 0;
491 c[3][start_y + x] = 0;
498 npx10 = (px / sqrtperte);
499 npy10 = (py / sqrtperte);
501 /* if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10);
502 if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10);
504 coefh = px % sqrtperte;
505 coefv = py % sqrtperte;
507 pos = (y * prevX + x) * 2;
508 coeffs[pos] = (npx10 + prevX * npy10) * 4;
510 if (!(coefh || coefv))
511 coeffs[pos + 1] = (sqrtperte * sqrtperte - 1);
513 coeffs[pos + 1] = ((sqrtperte - coefh) * (sqrtperte - coefv));
515 coeffs[pos + 1] |= (coefh * (sqrtperte - coefv)) << 8;
516 coeffs[pos + 1] |= ((sqrtperte - coefh) * coefv) << 16;
517 coeffs[pos + 1] |= (coefh * coefv) << 24;
520 pos10[pos] = npx10 + prevX * npy10;
522 if (!(coefh || coefv))
523 c[0][pos] = sqrtperte * sqrtperte - 1;
525 c[0][pos] = (sqrtperte - coefh) * (sqrtperte - coefv);
527 c[1][pos] = coefh * (sqrtperte - coefv);
528 c[2][pos] = (sqrtperte - coefh) * coefv;
529 c[3][pos] = coefh * coefv;
533 /* Advance start of line index */
540 mmx_zoom_size = prevX * prevY;
547 ppcsize4 = ((unsigned int) (prevX * prevY)) / 4;
550 ppcsize4 = ((unsigned int) (prevX * prevY));
555 for (position = 0; position < prevX * prevY; position++) {
556 getPixelRGB_ (pix1, pos10[position], &col1, goomdata->resolx,
558 getPixelRGB_ (pix1, pos10[position] + 1, &col2, goomdata->resolx,
560 getPixelRGB_ (pix1, pos10[position] + prevX, &col3, goomdata->resolx,
562 getPixelRGB_ (pix1, pos10[position] + prevX + 1, &col4, goomdata->resolx,
565 couleur.r = col1.r * c[0][position]
566 + col2.r * c[1][position]
567 + col3.r * c[2][position]
568 + col4.r * c[3][position];
569 couleur.r >>= zf->pertedec;
571 couleur.v = col1.v * c[0][position]
572 + col2.v * c[1][position]
573 + col3.v * c[2][position]
574 + col4.v * c[3][position];
575 couleur.v >>= zf->pertedec;
577 couleur.b = col1.b * c[0][position]
578 + col2.b * c[1][position]
579 + col3.b * c[2][position]
580 + col4.b * c[3][position];
581 couleur.b >>= zf->pertedec;
583 setPixelRGB_ (pix2, position, couleur, goomdata->resolx, goomdata->resoly);
590 pointFilter (GoomData * goomdata, Color c,
591 float t1, float t2, float t3, float t4, Uint cycle)
593 Uint *pix1 = goomdata->p1;
594 ZoomFilterData *zf = goomdata->zfd;
595 Uint x = (Uint) (zf->middleX + (int) (t1 * cos ((float) cycle / t3)));
596 Uint y = (Uint) (zf->middleY + (int) (t2 * sin ((float) cycle / t4)));
598 if ((x > 1) && (y > 1) && (x < goomdata->resolx - 2)
599 && (y < goomdata->resoly - 2)) {
600 setPixelRGB (pix1, x + 1, y, c, goomdata->resolx, goomdata->resoly);
601 setPixelRGB (pix1, x, y + 1, c, goomdata->resolx, goomdata->resoly);
602 setPixelRGB (pix1, x + 1, y + 1, WHITE, goomdata->resolx, goomdata->resoly);
603 setPixelRGB (pix1, x + 2, y + 1, c, goomdata->resolx, goomdata->resoly);
604 setPixelRGB (pix1, x + 1, y + 2, c, goomdata->resolx, goomdata->resoly);