ChameleonTV

Help to translate code from c to openframeworks…
This is “magic” effect from real-time video effector EffecTV.

http://effectv.sourceforge.net/chameleon.html

  
#define PLANES_DEPTH 6  
#define PLANES (1<<PLANES_DEPTH)   
  
static int start(void);  
static int stop(void);  
static int draw(RGB32 *src, RGB32 *dest);  
static int event(SDL_Event *);  
  
static char *effectname = "ChameleonTV";  
static int state = 0;  
static int mode = 0;  
static RGB32 *bgimage = NULL;  
static int bgIsSet;  
static unsigned int *sum = NULL;  
static unsigned char *timebuffer = NULL;  
static int plane;  
static void setBackground(RGB32 *src);  
static void drawDisappearing(RGB32 *src, RGB32 *dest);  
static void drawAppearing(RGB32 *src, RGB32 *dest);  
  
effect *chameleonRegister(void)  
{  
	effect *entry;  
	  
	sharedbuffer_reset();  
	sum = (unsigned int *)sharedbuffer_alloc(video_area * sizeof(unsigned int));  
	bgimage = (RGB32 *)sharedbuffer_alloc(video_area * PIXEL_SIZE);  
	if(sum == NULL || bgimage == NULL)  
		return NULL;  
  
	entry = (effect *)malloc(sizeof(effect));  
  
	if(entry == NULL) {  
		return NULL;  
	}  
	  
	entry->name = effectname;  
	entry->start = start;  
	entry->stop = stop;  
	entry->draw = draw;  
	entry->event = event;  
  
	return entry;  
}  
  
static int start(void)  
{  
	timebuffer = (unsigned char *)malloc(video_area * PLANES);  
	if(timebuffer == NULL)  
		return -1;  
  
	memset(timebuffer, 0, video_area * PLANES);  
	memset(sum, 0, video_area * sizeof(unsigned int));  
	bgIsSet = 0;  
	plane = 0;  
  
	state = 1;  
	return 0;  
}  
  
static int stop(void)  
{  
	if(state) {  
		if(timebuffer) {  
			free(timebuffer);  
			timebuffer = NULL;  
		}  
		state = 0;  
	}  
  
	return 0;  
}  
  
static int draw(RGB32 *src, RGB32 *dest)  
{  
	if(!bgIsSet) {  
		setBackground(src);  
	}  
  
	if(mode == 0) {  
		drawDisappearing(src, dest);  
	} else {  
		drawAppearing(src, dest);  
	}  
  
	return 0;  
}  
  
static void drawDisappearing(RGB32 *src, RGB32 *dest)  
{  
	int i;  
	unsigned int Y;  
	int r, g, b;  
	int R, G, B;  
	unsigned char *p;  
	RGB32 *q;  
	unsigned int *s;  
  
	p = timebuffer + plane * video_area;  
	q = bgimage;  
	s = sum;  
	for(i=0; i<video_area; i++) {  
		Y = *src++;  
  
		r = (Y>>16) & 0xff;  
		g = (Y>>8) & 0xff;  
		b = Y & 0xff;  
  
		R = (*q>>16) & 0xff;  
		G = (*q>>8) & 0xff;  
		B = *q & 0xff;  
  
		Y = (r + g * 2 + b) >> 2;  
		*s -= *p;  
		*s += Y;  
		*p = Y;  
		Y = (abs(((int)Y<<PLANES_DEPTH) - (int)(*s)) * 8)>>PLANES_DEPTH;  
		if(Y>255) Y = 255;  
  
		R += ((r - R) * Y) >> 8;  
		G += ((g - G) * Y) >> 8;  
		B += ((b - B) * Y) >> 8;  
		*dest++ = (R<<16)|(G<<8)|B;  
  
		p++;  
		q++;  
		s++;  
	}  
	plane++;  
	plane = plane & (PLANES-1);  
}  
  
static void drawAppearing(RGB32 *src, RGB32 *dest)  
{  
	int i;  
	unsigned int Y;  
	int r, g, b;  
	int R, G, B;  
	unsigned char *p;  
	RGB32 *q;  
	unsigned int *s;  
  
	p = timebuffer + plane * video_area;  
	q = bgimage;  
	s = sum;  
	for(i=0; i<video_area; i++) {  
		Y = *src++;  
  
		r = (Y>>16) & 0xff;  
		g = (Y>>8) & 0xff;  
		b = Y & 0xff;  
  
		R = (*q>>16) & 0xff;  
		G = (*q>>8) & 0xff;  
		B = *q & 0xff;  
  
		Y = (r + g * 2 + b) >> 2;  
		*s -= *p;  
		*s += Y;  
		*p = Y;  
		Y = (abs(((int)Y<<PLANES_DEPTH) - (int)(*s)) * 8)>>PLANES_DEPTH;  
		if(Y>255) Y = 255;  
  
		r += ((R - r) * Y) >> 8;  
		g += ((G - g) * Y) >> 8;  
		b += ((B - b) * Y) >> 8;  
		*dest++ = (r<<16)|(g<<8)|b;  
  
		p++;  
		q++;  
		s++;  
	}  
	plane++;  
	plane = plane & (PLANES-1);  
}  
  
static void setBackground(RGB32 *src)  
{  
	memcpy(bgimage, src, video_area * PIXEL_SIZE);  
	bgIsSet = 1;  
}  
  
static int event(SDL_Event *event)  
{  
	if(event->type == SDL_KEYDOWN) {  
		switch(event->key.keysym.sym) {  
		case SDLK_SPACE:  
			bgIsSet = 0;  
			break;  
		case SDLK_1:  
		case SDLK_KP1:  
			mode = 0;  
			break;  
		case SDLK_2:  
		case SDLK_KP2:  
			mode = 1;  
			break;  
		default:  
			break;  
		}  
	}  
	return 0;  
}