| /* Goom Project |
| * Copyright (C) <2003> iOS-Software |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| // --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY --- |
| |
| /* filter.c version 0.7 |
| * contient les filtres applicable a un buffer |
| * creation : 01/10/2000 |
| * -ajout de sinFilter() |
| * -ajout de zoomFilter() |
| * -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs |
| * -optimisation de sinFilter (utilisant une table de sin) |
| * -asm |
| * -optimisation de la procedure de generation du buffer de transformation |
| * la vitesse est maintenant comprise dans [0..128] au lieu de [0..100] |
| */ |
| |
| /* #define _DEBUG_PIXEL */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include <string.h> |
| #include <stdlib.h> |
| #include <math.h> |
| #include <stdio.h> |
| |
| #ifdef HAVE_INTTYPES_H |
| #include <inttypes.h> |
| #endif |
| |
| #include "goom_filters.h" |
| #include "goom_graphic.h" |
| #include "goom_tools.h" |
| #include "goom_plugin_info.h" |
| #include "goom_fx.h" |
| #include "v3d.h" |
| |
| /* TODO : MOVE THIS AWAY !!! */ |
| /* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */ |
| static inline void |
| setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c) |
| { |
| Pixel i; |
| |
| i.channels.b = c.b; |
| i.channels.g = c.v; |
| i.channels.r = c.r; |
| *(buffer + (x + y * goomInfo->screen.width)) = i; |
| } |
| |
| static inline void |
| setPixelRGB_ (Pixel * buffer, Uint x, Color c) |
| { |
| buffer[x].channels.r = c.r; |
| buffer[x].channels.g = c.v; |
| buffer[x].channels.b = c.b; |
| } |
| |
| static inline void |
| getPixelRGB_ (Pixel * buffer, Uint x, Color * c) |
| { |
| Pixel i = *(buffer + x); |
| |
| c->b = i.channels.b; |
| c->v = i.channels.g; |
| c->r = i.channels.r; |
| } |
| |
| /* END TODO */ |
| |
| |
| /* DEPRECATED */ |
| // retourne x>>s , en testant le signe de x |
| //#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s))) |
| //#define EFFECT_DISTORS 4 |
| //#define EFFECT_DISTORS_SL 2 |
| //#define INTERLACE_ADD 9 |
| //#define INTERLACE_AND 0xf |
| /* END DEPRECATED */ |
| |
| #define BUFFPOINTNB 16 |
| #define BUFFPOINTNBF 16.0f |
| #define BUFFPOINTMASK 0xffff |
| |
| #define sqrtperte 16 |
| /* faire : a % sqrtperte <=> a & pertemask */ |
| #define PERTEMASK 0xf |
| /* faire : a / sqrtperte <=> a >> PERTEDEC */ |
| #define PERTEDEC 4 |
| |
| /* pure c version of the zoom filter */ |
| static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, |
| unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio, |
| int precalCoef[BUFFPOINTNB][BUFFPOINTNB]); |
| |
| /* simple wrapper to give it the same proto than the others */ |
| void |
| zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS, |
| int *brutD, int buffratio, int precalCoef[16][16]) |
| { |
| c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef); |
| } |
| |
| static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]); |
| |
| |
| typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA |
| { |
| |
| PluginParam enabled_bp; |
| PluginParameters params; |
| |
| unsigned int *coeffs, *freecoeffs; |
| |
| signed int *brutS, *freebrutS; /* source */ |
| signed int *brutD, *freebrutD; /* dest */ |
| signed int *brutT, *freebrutT; /* temp (en cours de generation) */ |
| |
| guint32 zoom_width; |
| |
| unsigned int prevX, prevY; |
| |
| float general_speed; |
| int reverse; /* reverse the speed */ |
| char theMode; |
| int waveEffect; |
| int hypercosEffect; |
| int vPlaneEffect; |
| int hPlaneEffect; |
| char noisify; |
| int middleX, middleY; |
| |
| int mustInitBuffers; |
| int interlace_start; |
| |
| /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */ |
| int buffratio; |
| int *firedec; |
| |
| /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */ |
| int precalCoef[BUFFPOINTNB][BUFFPOINTNB]; |
| |
| /** calculatePXandPY statics */ |
| int wave; |
| int wavesp; |
| |
| } ZoomFilterFXWrapperData; |
| |
| |
| |
| |
| static inline void |
| zoomVector (v2g * vecteur, ZoomFilterFXWrapperData * data, float X, float Y) |
| { |
| float vx, vy; |
| float sq_dist = X * X + Y * Y; |
| |
| /* sx = (X < 0.0f) ? -1.0f : 1.0f; |
| sy = (Y < 0.0f) ? -1.0f : 1.0f; |
| */ |
| float coefVitesse = (1.0f + data->general_speed) / 50.0f; |
| |
| // Effects |
| |
| /* Centralized FX */ |
| |
| switch (data->theMode) { |
| case CRYSTAL_BALL_MODE: |
| coefVitesse -= (sq_dist - 0.3f) / 15.0f; |
| break; |
| case AMULETTE_MODE: |
| coefVitesse += sq_dist * 3.5f; |
| break; |
| case WAVE_MODE: |
| coefVitesse += sin (sq_dist * 20.0f) / 100.0f; |
| break; |
| case SCRUNCH_MODE: |
| coefVitesse += sq_dist / 10.0f; |
| break; |
| //case HYPERCOS1_MODE: |
| break; |
| //case HYPERCOS2_MODE: |
| break; |
| //case YONLY_MODE: |
| break; |
| case SPEEDWAY_MODE: |
| coefVitesse *= 4.0f * Y; |
| break; |
| default: |
| break; |
| } |
| |
| if (coefVitesse < -2.01f) |
| coefVitesse = -2.01f; |
| if (coefVitesse > 2.01f) |
| coefVitesse = 2.01f; |
| |
| vx = coefVitesse * X; |
| vy = coefVitesse * Y; |
| |
| /* Amulette 2 */ |
| // vx = X * tan(dist); |
| // vy = Y * tan(dist); |
| |
| /* Rotate */ |
| //vx = (X+Y)*0.1; |
| //vy = (Y-X)*0.1; |
| |
| |
| // Effects adds-on |
| |
| /* Noise */ |
| if (data->noisify) { |
| vx += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f; |
| vy += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f; |
| } |
| |
| /* Hypercos */ |
| if (data->hypercosEffect) { |
| vx += sin (Y * 10.0f) / 120.0f; |
| vy += sin (X * 10.0f) / 120.0f; |
| } |
| |
| /* H Plane */ |
| if (data->hPlaneEffect) |
| vx += Y * 0.0025f * data->hPlaneEffect; |
| |
| /* V Plane */ |
| if (data->vPlaneEffect) |
| vy += X * 0.0025f * data->vPlaneEffect; |
| |
| /* TODO : Water Mode */ |
| // if (data->waveEffect) |
| |
| vecteur->x = vx; |
| vecteur->y = vy; |
| } |
| |
| |
| /* |
| * Makes a stripe of a transform buffer (brutT) |
| * |
| * The transform is (in order) : |
| * Translation (-data->middleX, -data->middleY) |
| * Homothetie (Center : 0,0 Coeff : 2/data->prevX) |
| */ |
| static void |
| makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR) |
| { |
| // Position of the pixel to compute in pixmap coordinates |
| Uint x, y; |
| |
| // Where (verticaly) to stop generating the buffer stripe |
| int maxEnd; |
| |
| // Ratio from pixmap to normalized coordinates |
| float ratio = 2.0f / ((float) data->prevX); |
| |
| // Ratio from normalized to virtual pixmap coordinates |
| float inv_ratio = BUFFPOINTNBF / ratio; |
| float min = ratio / BUFFPOINTNBF; |
| |
| // Y position of the pixel to compute in normalized coordinates |
| float Y = ((float) (data->interlace_start - data->middleY)) * ratio; |
| |
| maxEnd = data->prevY; |
| if (maxEnd > (data->interlace_start + INTERLACE_INCR)) |
| maxEnd = (data->interlace_start + INTERLACE_INCR); |
| |
| for (y = data->interlace_start; |
| (y < data->prevY) && ((signed int) y < maxEnd); y++) { |
| Uint premul_y_prevX = y * data->prevX * 2; |
| float X = -((float) data->middleX) * ratio; |
| |
| for (x = 0; x < data->prevX; x++) { |
| v2g vector; |
| |
| zoomVector (&vector, data, X, Y); |
| |
| /* Finish and avoid null displacement */ |
| if (fabs (vector.x) < min) |
| vector.x = (vector.x < 0.0f) ? -min : min; |
| if (fabs (vector.y) < min) |
| vector.y = (vector.y < 0.0f) ? -min : min; |
| |
| data->brutT[premul_y_prevX] = |
| ((int) ((X - vector.x) * inv_ratio) + |
| ((int) (data->middleX * BUFFPOINTNB))); |
| data->brutT[premul_y_prevX + 1] = |
| ((int) ((Y - vector.y) * inv_ratio) + |
| ((int) (data->middleY * BUFFPOINTNB))); |
| premul_y_prevX += 2; |
| X += ratio; |
| } |
| Y += ratio; |
| } |
| data->interlace_start += INTERLACE_INCR; |
| if (y >= data->prevY - 1) |
| data->interlace_start = -1; |
| } |
| |
| |
| /* |
| * calculer px et py en fonction de x,y,middleX,middleY et theMode |
| * px et py indique la nouvelle position (en sqrtperte ieme de pixel) |
| * (valeur * 16) |
| |
| inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py) |
| { |
| if (data->theMode == WATER_MODE) { |
| int yy; |
| |
| yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10; |
| if (yy < 0) |
| yy = 0; |
| if (yy >= (signed int)goomInfo->screen.height) |
| yy = goomInfo->screen.height - 1; |
| |
| *px = (x << 4) + data->firedec[yy] + (data->wave / 10); |
| *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130); |
| |
| data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3); |
| if (data->wave < -10) |
| data->wavesp += 2; |
| if (data->wave > 10) |
| data->wavesp -= 2; |
| data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3); |
| if (data->wavesp > 100) |
| data->wavesp = (data->wavesp * 9) / 10; |
| } |
| else { |
| int dist = 0, vx9, vy9; |
| int vx, vy; |
| int ppx, ppy; |
| int fvitesse = data->vitesse << 4; |
| |
| if (data->noisify) { |
| x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify); |
| y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify); |
| } |
| vx = (x - data->middleX) << 9; |
| vy = (y - data->middleY) << 9; |
| |
| if (data->hPlaneEffect) |
| vx += data->hPlaneEffect * (y - data->middleY); |
| |
| if (data->vPlaneEffect) |
| vy += data->vPlaneEffect * (x - data->middleX); |
| |
| if (data->waveEffect) { |
| fvitesse *= |
| 1024 + |
| ShiftRight (goomInfo->sintable |
| [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6); |
| fvitesse /= 1024; |
| } |
| |
| if (data->hypercosEffect) { |
| vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1); |
| vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1); |
| } |
| |
| vx9 = ShiftRight (vx, 9); |
| vy9 = ShiftRight (vy, 9); |
| dist = vx9 * vx9 + vy9 * vy9; |
| |
| switch (data->theMode) { |
| case WAVE_MODE: |
| fvitesse *= |
| 1024 + |
| ShiftRight (goomInfo->sintable |
| [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6); |
| fvitesse>>=10; |
| break; |
| case CRYSTAL_BALL_MODE: |
| fvitesse += (dist >> (10-EFFECT_DISTORS_SL)); |
| break; |
| case AMULETTE_MODE: |
| fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL)); |
| break; |
| case SCRUNCH_MODE: |
| fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL)); |
| break; |
| case HYPERCOS1_MODE: |
| vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1); |
| vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1); |
| break; |
| case HYPERCOS2_MODE: |
| vx = |
| vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0); |
| vy = |
| vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0); |
| fvitesse = 128 << 4; |
| break; |
| case YONLY_MODE: |
| fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6); |
| fvitesse >>= 10; |
| break; |
| case SPEEDWAY_MODE: |
| fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL)); |
| break; |
| } |
| |
| if (fvitesse < -3024) |
| fvitesse = -3024; |
| |
| if (vx < 0) // pb avec decalage sur nb negatif |
| ppx = -(-(vx * fvitesse) >> 16); |
| // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile) |
| // * * * * * 9 = nb chiffre virgule de vx) |
| else |
| ppx = ((vx * fvitesse) >> 16); |
| |
| if (vy < 0) |
| ppy = -(-(vy * fvitesse) >> 16); |
| else |
| ppy = ((vy * fvitesse) >> 16); |
| |
| *px = (data->middleX << 4) + ppx; |
| *py = (data->middleY << 4) + ppy; |
| } |
| } |
| */ |
| |
| |
| |
| static void |
| c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, unsigned int prevY, |
| signed int *brutS, signed int *brutD, int buffratio, int precalCoef[16][16]) |
| { |
| int myPos, myPos2; |
| Color couleur; |
| |
| unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC; |
| |
| int bufsize = prevX * prevY * 2; |
| int bufwidth = prevX; |
| |
| expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val = |
| expix1[prevX * prevY - prevX].val = 0; |
| |
| for (myPos = 0; myPos < bufsize; myPos += 2) { |
| Color col1, col2, col3, col4; |
| int c1, c2, c3, c4, px, py; |
| int pos; |
| int coeffs; |
| |
| int brutSmypos = brutS[myPos]; |
| |
| myPos2 = myPos + 1; |
| |
| px = brutSmypos + (((brutD[myPos] - |
| brutSmypos) * buffratio) >> BUFFPOINTNB); |
| brutSmypos = brutS[myPos2]; |
| py = brutSmypos + (((brutD[myPos2] - |
| brutSmypos) * buffratio) >> BUFFPOINTNB); |
| |
| if ((py >= ay) || (px >= ax)) { |
| pos = coeffs = 0; |
| } else { |
| pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC)); |
| /* coef en modulo 15 */ |
| coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK]; |
| } |
| getPixelRGB_ (expix1, pos, &col1); |
| getPixelRGB_ (expix1, pos + 1, &col2); |
| getPixelRGB_ (expix1, pos + bufwidth, &col3); |
| getPixelRGB_ (expix1, pos + bufwidth + 1, &col4); |
| |
| c1 = coeffs; |
| c2 = (c1 >> 8) & 0xFF; |
| c3 = (c1 >> 16) & 0xFF; |
| c4 = (c1 >> 24) & 0xFF; |
| c1 = c1 & 0xff; |
| |
| couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4; |
| if (couleur.r > 5) |
| couleur.r -= 5; |
| couleur.r >>= 8; |
| |
| couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4; |
| if (couleur.v > 5) |
| couleur.v -= 5; |
| couleur.v >>= 8; |
| |
| couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4; |
| if (couleur.b > 5) |
| couleur.b -= 5; |
| couleur.b >>= 8; |
| |
| setPixelRGB_ (expix2, myPos >> 1, couleur); |
| } |
| } |
| |
| /** generate the water fx horizontal direction buffer */ |
| static void |
| generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo, |
| ZoomFilterFXWrapperData * data) |
| { |
| |
| int loopv; |
| int decc = goom_irand (goomInfo->gRandom, 8) - 4; |
| int spdc = goom_irand (goomInfo->gRandom, 8) - 4; |
| int accel = goom_irand (goomInfo->gRandom, 8) - 4; |
| |
| for (loopv = data->prevY; loopv != 0;) { |
| |
| loopv--; |
| data->firedec[loopv] = decc; |
| decc += spdc / 10; |
| spdc += |
| goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3); |
| |
| if (decc > 4) |
| spdc -= 1; |
| if (decc < -4) |
| spdc += 1; |
| |
| if (spdc > 30) |
| spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10; |
| if (spdc < -30) |
| spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10; |
| |
| if (decc > 8 && spdc > 1) |
| spdc -= goom_irand (goomInfo->gRandom, 3) - 2; |
| |
| if (decc < -8 && spdc < -1) |
| spdc += goom_irand (goomInfo->gRandom, 3) + 2; |
| |
| if (decc > 8 || decc < -8) |
| decc = decc * 8 / 9; |
| |
| accel += |
| goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2); |
| if (accel > 20) |
| accel -= 2; |
| if (accel < -20) |
| accel += 2; |
| } |
| } |
| |
| |
| |
| /** |
| * Main work for the dynamic displacement map. |
| * |
| * Reads data from pix1, write to pix2. |
| * |
| * Useful datas for this FX are stored in ZoomFilterData. |
| * |
| * If you think that this is a strange function name, let me say that a long time ago, |
| * there has been a slow version and a gray-level only one. Then came these function, |
| * fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image. |
| * So that is why you have this name, for the nostalgy of the first days of goom |
| * when it was just a tiny program writen in Turbo Pascal on my i486... |
| */ |
| void |
| zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2, |
| ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult) |
| { |
| Uint x, y; |
| |
| ZoomFilterFXWrapperData *data = |
| (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data; |
| |
| if (!BVAL (data->enabled_bp)) |
| return; |
| |
| /** changement de taille **/ |
| if ((data->prevX != resx) || (data->prevY != resy)) { |
| data->prevX = resx; |
| data->prevY = resy; |
| |
| if (data->brutS) |
| free (data->freebrutS); |
| data->brutS = 0; |
| if (data->brutD) |
| free (data->freebrutD); |
| data->brutD = 0; |
| if (data->brutT) |
| free (data->freebrutT); |
| data->brutT = 0; |
| |
| data->middleX = resx / 2; |
| data->middleY = resy / 2; |
| data->mustInitBuffers = 1; |
| if (data->firedec) |
| free (data->firedec); |
| data->firedec = 0; |
| } |
| |
| if (data->interlace_start != -2) |
| zf = NULL; |
| |
| /** changement de config **/ |
| if (zf) { |
| data->reverse = zf->reverse; |
| data->general_speed = (float) (zf->vitesse - 128) / 128.0f; |
| if (data->reverse) |
| data->general_speed = -data->general_speed; |
| data->middleX = zf->middleX; |
| data->middleY = zf->middleY; |
| data->theMode = zf->mode; |
| data->hPlaneEffect = zf->hPlaneEffect; |
| data->vPlaneEffect = zf->vPlaneEffect; |
| data->waveEffect = zf->waveEffect; |
| data->hypercosEffect = zf->hypercosEffect; |
| data->noisify = zf->noisify; |
| data->interlace_start = 0; |
| } |
| |
| |
| if (data->mustInitBuffers) { |
| |
| data->mustInitBuffers = 0; |
| data->freebrutS = |
| (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int)); |
| data->brutS = |
| (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128); |
| |
| data->freebrutD = |
| (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int)); |
| data->brutD = |
| (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128); |
| |
| data->freebrutT = |
| (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int)); |
| data->brutT = |
| (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128); |
| |
| data->buffratio = 0; |
| |
| data->firedec = (int *) malloc (data->prevY * sizeof (int)); |
| generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data); |
| |
| data->interlace_start = 0; |
| makeZoomBufferStripe (data, resy); |
| |
| /* Copy the data from temp to dest and source */ |
| memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int)); |
| memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int)); |
| } |
| |
| /* generation du buffer de trans */ |
| if (data->interlace_start == -1) { |
| |
| /* sauvegarde de l'etat actuel dans la nouvelle source |
| * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */ |
| y = data->prevX * data->prevY * 2; |
| for (x = 0; x < y; x += 2) { |
| int brutSmypos = data->brutS[x]; |
| int x2 = x + 1; |
| |
| data->brutS[x] = |
| brutSmypos + (((data->brutD[x] - |
| brutSmypos) * data->buffratio) >> BUFFPOINTNB); |
| brutSmypos = data->brutS[x2]; |
| data->brutS[x2] = |
| brutSmypos + (((data->brutD[x2] - |
| brutSmypos) * data->buffratio) >> BUFFPOINTNB); |
| } |
| data->buffratio = 0; |
| } |
| |
| if (data->interlace_start == -1) { |
| signed int *tmp; |
| |
| tmp = data->brutD; |
| data->brutD = data->brutT; |
| data->brutT = tmp; |
| tmp = data->freebrutD; |
| data->freebrutD = data->freebrutT; |
| data->freebrutT = tmp; |
| data->interlace_start = -2; |
| } |
| |
| if (data->interlace_start >= 0) { |
| /* creation de la nouvelle destination */ |
| makeZoomBufferStripe (data, resy / 16); |
| } |
| |
| if (switchIncr != 0) { |
| data->buffratio += switchIncr; |
| if (data->buffratio > BUFFPOINTMASK) |
| data->buffratio = BUFFPOINTMASK; |
| } |
| |
| if (switchMult != 1.0f) { |
| data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) + |
| (float) data->buffratio * switchMult); |
| } |
| |
| data->zoom_width = data->prevX; |
| |
| goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2, |
| data->brutS, data->brutD, data->buffratio, data->precalCoef); |
| } |
| |
| static void |
| generatePrecalCoef (int precalCoef[16][16]) |
| { |
| int coefh, coefv; |
| |
| for (coefh = 0; coefh < 16; coefh++) { |
| for (coefv = 0; coefv < 16; coefv++) { |
| |
| int i; |
| int diffcoeffh; |
| int diffcoeffv; |
| |
| diffcoeffh = sqrtperte - coefh; |
| diffcoeffv = sqrtperte - coefv; |
| |
| if (!(coefh || coefv)) { |
| i = 255; |
| } else { |
| Uint i1, i2, i3, i4; |
| |
| i1 = diffcoeffh * diffcoeffv; |
| i2 = coefh * diffcoeffv; |
| i3 = diffcoeffh * coefv; |
| i4 = coefh * coefv; |
| |
| // TODO: faire mieux... |
| if (i1) |
| i1--; |
| if (i2) |
| i2--; |
| if (i3) |
| i3--; |
| if (i4) |
| i4--; |
| |
| i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24); |
| } |
| precalCoef[coefh][coefv] = i; |
| } |
| } |
| } |
| |
| /* VisualFX Wrapper */ |
| |
| static void |
| zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info) |
| { |
| ZoomFilterFXWrapperData *data = |
| (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData)); |
| |
| data->coeffs = 0; |
| data->freecoeffs = 0; |
| data->brutS = 0; |
| data->freebrutS = 0; |
| data->brutD = 0; |
| data->freebrutD = 0; |
| data->brutT = 0; |
| data->freebrutT = 0; |
| data->prevX = 0; |
| data->prevY = 0; |
| |
| data->mustInitBuffers = 1; |
| data->interlace_start = -2; |
| |
| data->general_speed = 0.0f; |
| data->reverse = 0; |
| data->theMode = AMULETTE_MODE; |
| data->waveEffect = 0; |
| data->hypercosEffect = 0; |
| data->vPlaneEffect = 0; |
| data->hPlaneEffect = 0; |
| data->noisify = 2; |
| |
| /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */ |
| data->buffratio = 0; |
| data->firedec = 0; |
| |
| data->wave = data->wavesp = 0; |
| |
| secure_b_param (&data->enabled_bp, "Enabled", 1); |
| |
| plugin_parameters (&data->params, "Zoom Filter", 1); |
| data->params.params[0] = &data->enabled_bp; |
| |
| _this->params = &data->params; |
| _this->fx_data = (void *) data; |
| |
| /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */ |
| generatePrecalCoef (data->precalCoef); |
| } |
| |
| static void |
| zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this) |
| { |
| ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) _this->fx_data; |
| |
| if (data->freebrutT) |
| free (data->freebrutT); |
| if (data->freebrutS) |
| free (data->freebrutS); |
| if (data->freebrutD) |
| free (data->freebrutD); |
| if (data->firedec) |
| free (data->firedec); |
| |
| goom_plugin_parameters_free (_this->params); |
| |
| free (_this->fx_data); |
| } |
| |
| static void |
| zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src, |
| Pixel * dest, PluginInfo * info) |
| { |
| } |
| |
| void |
| zoomFilterVisualFXWrapper_create (VisualFX * fx) |
| { |
| fx->init = zoomFilterVisualFXWrapper_init; |
| fx->free = zoomFilterVisualFXWrapper_free; |
| fx->apply = zoomFilterVisualFXWrapper_apply; |
| fx->params = NULL; |
| fx->fx_data = NULL; |
| } |
| |
| |
| /* TODO : MOVE THIS AWAY */ |
| |
| void |
| pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2, |
| float t3, float t4, Uint cycle) |
| { |
| Uint x = (Uint) ((int) (goomInfo->screen.width / 2) |
| + (int) (t1 * cos ((float) cycle / t3))); |
| Uint y = (Uint) ((int) (goomInfo->screen.height / 2) |
| + (int) (t2 * sin ((float) cycle / t4))); |
| |
| if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2) |
| && (y < goomInfo->screen.height - 2)) { |
| setPixelRGB (goomInfo, pix1, x + 1, y, c); |
| setPixelRGB (goomInfo, pix1, x, y + 1, c); |
| setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE); |
| setPixelRGB (goomInfo, pix1, x + 2, y + 1, c); |
| setPixelRGB (goomInfo, pix1, x + 1, y + 2, c); |
| } |
| } |