Files
veejay/veejay-current/veejay-server/libvje/effects/fisheye.c_wip
Niels Elburg d8e6f98d53 Initial checkin of veejay 1.4
git-svn-id: svn://code.dyne.org/veejay/trunk@1172 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
2008-11-10 20:16:24 +00:00

241 lines
5.4 KiB
Plaintext

/*
* Linux VeeJay
*
* Copyright(C)2004 Niels Elburg <elburg@hio.hen.nl>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License , or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA.
*/
#include <config.h>
#include "fisheye.h"
#include <stdlib.h>
#include "common.h"
#include <math.h>
vj_effect *fisheye_init(int w, int h)
{
vj_effect *ve = (vj_effect *) malloc(sizeof(vj_effect));
ve->num_params = 1;
ve->defaults = (int *) malloc(sizeof(int) * ve->num_params); /* default values */
ve->limits[0] = (int *) malloc(sizeof(int) * ve->num_params); /* min */
ve->limits[1] = (int *) malloc(sizeof(int) * ve->num_params); /* max */
ve->limits[0][0] = -1000;
ve->limits[1][0] = 1000;
ve->defaults[0] = 1;
ve->description = "Fish Eye";
ve->sub_format = 1;
ve->extra_frame = 0;
ve->has_internal_data= 1;
return ve;
}
static double *polar_map;
static double *fish_angle;
static int *cached_coords;
static uint8_t *buf[3];
int fisheye_malloc(int w, int h)
{
int x,y;
int h2=h/2;
int w2=w/2;
int p =0;
buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h );
if(!buf[0]) return -1;
buf[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h );
if(!buf[1]) return -1;
buf[2] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h );
if(!buf[2]) return -1;
polar_map = (double*) vj_malloc(sizeof(double) * w* h );
if(!polar_map) return -1;
fish_angle = (double*) vj_malloc(sizeof(double) * w* h );
if(!fish_angle) return -1;
cached_coords = (int*) vj_malloc(sizeof(int) * w * h);
if(!cached_coords) return -1;
for(y=(-1 *h2); y < (h-h2); y++)
{
for(x= (-1 * w2); x < (w-w2); x++)
{
double res;
fast_sqrt( res,(double) (y*y+x*x));
p = (h2+y)*w+(w2+x);
polar_map[p] = res;
//polar_map[p] = sqrt( y*y + x*x );
fish_angle[p] = atan2( (float) y, x);
}
}
return 1;
}
void fisheye_free()
{
if(buf[0]) free(buf[0]);
if(buf[1]) free(buf[1]);
if(buf[2]) free(buf[2]);
if(polar_map) free(polar_map);
if(fish_angle) free(fish_angle);
if(cached_coords) free(cached_coords);
}
static double __fisheye(double r,double v, double e)
{
return (exp( r / v )-1) / e;
}
static double __fisheye_i(double r, double v, double e)
{
return v * log(1 + e * r);
}
extern void *(* veejay_memcpy)(void *to, const void *from, size_t len) ;
static int _v = 0;
void fisheye_apply(uint8_t *yuv[3], int w, int h, int v )
{
int i;
const int len = w * h;
double (*pf)(double a, double b, double c);
if( v==0) v =1;
if( v < 0 ) {
pf = &__fisheye_i;
v = v * -1;
}
else {
pf = &__fisheye;
}
if( v != _v )
{
const double curve = 0.001 * v;
const unsigned int R = h/2;
const double coeef = R / log(curve * R + 1);
/* pre calculate */
int i;
int px,py,x,y;
double r,a,co,si;
const int w2 = w/2;
const int h2 = h/2;
int j=0;
int c = (h2 * w + w2);
int count = 0;
for (i=1; i<R; i++) {
x = polar_map[count];
count++;
r = exp( ( x / curve ) -1 ) / curve;
co = (i+0.5) / r;
si = co;
px = r * co;
py = r * si;
if(px > w2) px = w2;
if(py > h2) py = h2;
cached_coords[c+i+((i-1)*w)] = ((py-1) * w) + px;
cached_coords[c-i+((i-1)*w)+1] = ((py-1) * w) - px;
cached_coords[c+i-((i-1)*w)-w] = -((py-1) * w) + px;
cached_coords[c-i-((i-1)*w)-w+1] = -((py-1) * w) - px;
for (j=1; j<i; j++) {
x = polar_map[count];
count++;
r = exp( ( x / curve ) -1 ) / curve;
co = (i+0.5) / r;
si = (j+0.5) / r;
px = r*co;
py = r*si;
if(px > w2) px = w2;
if(py > h2) py = h2;
cached_coords[c+i+((j-1)*w)] = ((py-1) * w) + px;
cached_coords[c-i+((j-1)*w)+1] = ((py-1) * w) - px;
cached_coords[c+i-((j-1)*w)-w] = -((py-1) * w) + px;
cached_coords[c-i-((j-1)*w)-w+1] = -((py-1) * w) - px;
cached_coords[c+j+((i-1)*w)] = ((px-1) * w) + py;
cached_coords[c-j+((i-1)*w)+1] = ((px-1) * w) - py;
cached_coords[c+j-((i-1)*w)-w] = -((px-1) * w) + py;
cached_coords[c-j-((i-1)*w)-w+1] = -((px-1) * w) - py;
}
}
/* for(i=0; i < len; i++)
{
r = polar_map[i];
a = fish_angle[i];
if(r <= R)
{
r = pf( r, coeef, curve );
sin_cos( si,co, a);
px =(int) ( r * co);
py =(int) ( r * si);
px += w2;
py += h2;
if(px < 0) px =0;
if(px > w) px = w;
if(py < 0) py = 0;
if(py >= (h-1)) py = h-1;
cached_coords[i] = (py * w)+px;
}
else
{
cached_coords[i] = -1;
}
}
*/
_v = v;
}
veejay_memcpy(buf[0], yuv[0],(w*h));
veejay_memcpy(buf[1], yuv[1],(w*h));
veejay_memcpy(buf[2], yuv[2],(w*h));
for(i=0; i < len; i++)
{
if(cached_coords[i] == -1)
{
yuv[0][i] = 16;
yuv[1][i] = 128;
yuv[2][i] = 128;
}
else
{
yuv[0][i] = buf[0][ cached_coords[i] ];
yuv[1][i] = buf[1][ cached_coords[i] ];
yuv[2][i] = buf[2][ cached_coords[i] ];
}
}
}