1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/*
* EffecTV - Realtime Digital Video Effector
* Copyright (C) 2001-2006 FUKUCHI Kentaro
*
* EdgeTV - detects edge and display it in good old computer way.
* Copyright (C) 2001-2002 FUKUCHI Kentaro
*
* The idea of EdgeTV is taken from Adrian Likins's effector script for GIMP,
* `Predator effect.'
*
* The algorithm of the original script pixelizes the image at first, then
* it adopts the edge detection filter to the image. It also adopts MaxRGB
* filter to the image. This is not used in EdgeTV.
* This code is highly optimized and employs many fake algorithms. For example,
* it devides a value with 16 instead of using sqrt() in line 132-134. It is
* too hard for me to write detailed comment in this code in English.
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "EffecTV.h"
#include "utils.h"
static int start(void);
static int stop(void);
static int draw(RGB32 *src, RGB32 *dest);
static char *effectname = "EdgeTV";
static int stat;
static RGB32 *map;
static int map_width;
static int map_height;
static int video_width_margin;
effect *edgeRegister(void)
{
effect *entry;
map_width = video_width / 4;
map_height = video_height / 4;
video_width_margin = video_width - map_width * 4;
sharedbuffer_reset();
map = (RGB32 *)sharedbuffer_alloc(map_width*map_height*PIXEL_SIZE*2);
if(map == 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 = NULL;
return entry;
}
static int start(void)
{
memset(map, 0, map_width * map_height * PIXEL_SIZE * 2);
stat = 1;
return 0;
}
static int stop(void)
{
stat = 0;
return 0;
}
static int draw(RGB32 *src, RGB32 *dest)
{
int x, y;
int r, g, b;
RGB32 p, q;
RGB32 v0, v1, v2, v3;
src += video_width*4+4;
dest += video_width*4+4;
for(y=1; y<map_height-1; y++) {
for(x=1; x<map_width-1; x++) {
p = *src;
q = *(src - 4);
/* difference between the current pixel and right neighbor. */
r = ((int)(p & 0xff0000) - (int)(q & 0xff0000))>>16;
g = ((int)(p & 0x00ff00) - (int)(q & 0x00ff00))>>8;
b = ((int)(p & 0x0000ff) - (int)(q & 0x0000ff));
r *= r; /* Multiply itself and divide it with 16, instead of */
g *= g; /* using abs(). */
b *= b;
r = r>>5; /* To lack the lower bit for saturated addition, */
g = g>>5; /* devide the value with 32, instead of 16. It is */
b = b>>4; /* same as `v2 &= 0xfefeff' */
if(r>127) r = 127;
if(g>127) g = 127;
if(b>255) b = 255;
v2 = (r<<17)|(g<<9)|b;
/* difference between the current pixel and upper neighbor. */
q = *(src - video_width*4);
r = ((int)(p & 0xff0000) - (int)(q & 0xff0000))>>16;
g = ((int)(p & 0x00ff00) - (int)(q & 0x00ff00))>>8;
b = ((int)(p & 0x0000ff) - (int)(q & 0x0000ff));
r *= r;
g *= g;
b *= b;
r = r>>5;
g = g>>5;
b = b>>4;
if(r>127) r = 127;
if(g>127) g = 127;
if(b>255) b = 255;
v3 = (r<<17)|(g<<9)|b;
v0 = map[(y-1)*map_width*2+x*2];
v1 = map[y*map_width*2+(x-1)*2+1];
map[y*map_width*2+x*2] = v2;
map[y*map_width*2+x*2+1] = v3;
r = v0 + v1;
g = r & 0x01010100;
dest[0] = r | (g - (g>>8));
r = v0 + v3;
g = r & 0x01010100;
dest[1] = r | (g - (g>>8));
dest[2] = v3;
dest[3] = v3;
r = v2 + v1;
g = r & 0x01010100;
dest[video_width] = r | (g - (g>>8));
r = v2 + v3;
g = r & 0x01010100;
dest[video_width+1] = r | (g - (g>>8));
dest[video_width+2] = v3;
dest[video_width+3] = v3;
dest[video_width*2] = v2;
dest[video_width*2+1] = v2;
dest[video_width*3] = v2;
dest[video_width*3+1] = v2;
src += 4;
dest += 4;
}
src += video_width*3+8+video_width_margin;
dest += video_width*3+8+video_width_margin;
}
return 0;
}
|