#include "frei0r.h"
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
/**
* This is our instance.
* It has a buffer allocated to place a small version of the incoming
* frame into.
*/
typedef struct teh_roxx0r
{
unsigned int width; // frame size in x-dimension
unsigned int height; // frame size in y-dimension
unsigned int block_size; // x/y size of one block
double change_speed;
double last_time;
double time_stack;
uint32_t* small_block; // buffer to write downscaled frame
} tehRoxx0r_instance_t;
// returns greatest common divisor of to int numbers
int gcd(int a, int b);
int f0r_init()
{
return 1;
}
void f0r_deinit()
{ /* no initialization required */ }
void f0r_get_plugin_info(f0r_plugin_info_t* tehRoxx0rInfo)
{
tehRoxx0rInfo->name = "TehRoxx0r";
tehRoxx0rInfo->author = "Coma";
tehRoxx0rInfo->plugin_type = F0R_PLUGIN_TYPE_FILTER;
tehRoxx0rInfo->color_model = F0R_COLOR_MODEL_PACKED32;
tehRoxx0rInfo->frei0r_version = FREI0R_MAJOR_VERSION;
tehRoxx0rInfo->major_version = 0;
tehRoxx0rInfo->minor_version = 9;
tehRoxx0rInfo->num_params = 1;
tehRoxx0rInfo->explanation = "Something videowall-ish";
}
void f0r_get_param_info(f0r_param_info_t* info, int param_index)
{
info->name = "Interval";
info->type = F0R_PARAM_DOUBLE;
info->explanation = "Changing speed of small blocks";
}
f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
{
int blocksize;
tehRoxx0r_instance_t* inst = (tehRoxx0r_instance_t*)calloc(1, sizeof(*inst));
inst->width = width; inst->height = height;
inst->change_speed = 0.01;
// get greatest common divisor
blocksize = gcd(width, height);
// this will sometimes be to large, so roughly estimate a check
if(blocksize >= (width/3) || blocksize >= (height/3))
blocksize /= 2;
inst->block_size = blocksize;
inst->small_block =
(uint32_t*)malloc(sizeof(uint32_t)*inst->block_size*inst->block_size);
return (f0r_instance_t)inst;
}
void f0r_destruct(f0r_instance_t instance)
{
tehRoxx0r_instance_t* inst = (tehRoxx0r_instance_t*)instance;
free(inst->small_block);
free(inst);
}
void f0r_set_param_value(f0r_instance_t instance,
f0r_param_t param, int param_index)
{
tehRoxx0r_instance_t* inst = (tehRoxx0r_instance_t *)instance;
// (tehRoxx0r_instance_t*)malloc(sizeof(tehRoxx0r_instance_t));
switch(param_index)
{
case 0:
inst->change_speed = *((double*)param);
break;
};
}
void f0r_get_param_value(f0r_instance_t instance,
f0r_param_t param, int param_index)
{
tehRoxx0r_instance_t* inst = (tehRoxx0r_instance_t *)instance;
// (tehRoxx0r_instance_t*)malloc(sizeof(tehRoxx0r_instance_t));
switch(param_index)
{
case 0:
*((double*)param) = inst->change_speed;
break;
};
}
void f0r_update(f0r_instance_t instance, double time,
const uint32_t* inframe, uint32_t* outframe)
{
assert(instance);
tehRoxx0r_instance_t* inst = (tehRoxx0r_instance_t*)instance;
unsigned int w = inst->width;
unsigned int h = inst->height;
uint32_t* dst;
const uint32_t* src;
uint32_t* small_block = inst->small_block;
unsigned int x,y;
unsigned int small_x, small_y;
unsigned int small_w, small_h;
double step_x, step_y;
unsigned int pos_w, pos_h;
// get x/y-size of middle block
small_w = w-2*inst->block_size;
small_h = h-2*inst->block_size;
// get interpolation step for that
step_x = (double)w / (double)small_w;
step_y = (double)h / (double)small_h;
// make background black transparent
memset(outframe, 0, w * h * sizeof(uint32_t));
// copy a downscaled version into the middle of the result frame
// (blocksize to x-blocksize and blocksize to y-blocksize)
for(y = 0, small_y=inst->block_size;small_y<h-inst->block_size;small_y++,
y=step_y*(small_y-inst->block_size))
{
src = inframe + y*w;
dst = outframe + small_y*w + inst->block_size;
for(x=0;x<w-2*inst->block_size;x++)
{
*dst++ = *(src + (int)(x*step_x));
}
}
// add elapsed time to timestack
inst->time_stack += (time-inst->last_time);
// get interpolation step size
step_x = w / inst->block_size;
step_y = h / inst->block_size;
// create a small picture
for(y=0,small_y=0; small_y<inst->block_size; small_y++,y+=step_y)
{
src = inframe + y*w;
dst = small_block + small_y*inst->block_size;
for(x=0,small_x = 0; small_x<inst->block_size; small_x++)//,x+=step_x)
{
*dst++ = *src;
src += (unsigned int)step_x;
}
}
// do we actually changed anything?
if(inst->time_stack > inst->change_speed)
{
// get random position
pos_w = inst->block_size *
(unsigned int)(rand()/(double)RAND_MAX * ((w / inst->block_size)));
pos_h = inst->block_size *
(unsigned int)(rand()/(double)RAND_MAX * ((h / inst->block_size)));
// now copy to some (random) places along the border of
// the incoming frame.....
dst = outframe + pos_w;
src = small_block;
for(x=0; x<inst->block_size;
x++, dst += w, src += inst->block_size)
memcpy(dst, src, sizeof(int32_t)*inst->block_size);
dst = outframe + pos_h * w;
src = small_block;
for(x=0; x<inst->block_size;
x++, dst += w, src += inst->block_size)
memcpy(dst, src, sizeof(int32_t)*inst->block_size);
dst = outframe + pos_h* w + w - inst->block_size;
src = small_block;
for(x=0; x<inst->block_size;
x++, dst += w, src += inst->block_size)
memcpy(dst, src, sizeof(int32_t)*inst->block_size);
dst = outframe + (h-inst->block_size) *w + pos_w;
src = small_block;
for(x=0; x<inst->block_size;
x++, dst += w, src += inst->block_size)
memcpy(dst, src, sizeof(int32_t)*inst->block_size);
// reset timestack
inst->time_stack = 0.0;
}
inst->last_time = time;
}
// greatest common divisor. this will never become smaller than 8.
int gcd(int a, int b)
{
if(b==0) return a;
else return gcd(b, a%b);
}