1 #include "colormodels.h"
3 #include "plugincolors.h"
11 unsigned int EffectTV::fastrand_val = 0;
13 EffectTV::EffectTV(int w, int h)
17 background = (unsigned char*)new uint16_t[w * h];
18 diff = new unsigned char[w * h];
19 diff2 = new unsigned char[w * h];
33 int EffectTV::yuv_init()
37 for(i = 0; i < 256; i++)
39 YtoRGB[i] = (int)( 1.164 * (i - 16));
40 VtoR[i] = (int)( 1.596 * (i - 128));
41 VtoG[i] = (int)(-0.813 * (i - 128));
42 UtoG[i] = (int)(-0.391 * (i - 128));
43 UtoB[i] = (int)( 2.018 * (i - 128));
44 RtoY[i] = (int)( 0.257 * i);
45 RtoU[i] = (int)(-0.148 * i);
46 RtoV[i] = (int)( 0.439 * i);
47 GtoY[i] = (int)( 0.504 * i);
48 GtoU[i] = (int)(-0.291 * i);
49 GtoV[i] = (int)(-0.368 * i);
50 BtoY[i] = (int)( 0.098 * i);
51 BtoV[i] = (int)(-0.071 * i);
52 //printf("EffectTV::yuv_init %d %d %d\n", RtoY[i], GtoY[i], BtoY[i]);
58 #define FRAME_TO_EFFECTTV(type, components) \
60 for(int i = 0; i < width; i++) \
62 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
63 type *input_row = ((type**)frame->get_rows())[i]; \
65 for(int j = 0; j < width; j++) \
67 if(sizeof(type) == 1) \
69 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 16; \
70 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]) << 8; \
71 row[j * sizeof(uint32_t)] |= input_row[2]; \
75 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 8; \
76 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]); \
77 row[j * sizeof(uint32_t)] |= input_row[2] >> 8; \
79 input_row += components; \
86 void EffectTV::frame_to_effecttv(VFrame *frame, uint32_t *tmp)
88 int width = frame->get_w();
89 int height = frame->get_h();
91 switch(frame->get_color_model())
95 FRAME_TO_EFFECTTV(uint8_t, 3);
100 FRAME_TO_EFFECTTV(uint8_t, 4);
105 FRAME_TO_EFFECTTV(uint16_t, 3);
108 case BC_RGBA16161616:
109 case BC_YUVA16161616:
110 FRAME_TO_EFFECTTV(uint16_t, 4);
117 #define EFFECTTV_TO_FRAME(type, components) \
119 for(int i = 0; i < width; i++) \
121 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
122 type *output_row = ((type**)frame->get_rows())[i]; \
124 for(int j = 0; j < width; j++) \
126 if(sizeof(type) == 1) \
128 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 16; \
129 output_row[1] = (row[j * sizeof(uint32_t)] & 0xff00) >> 8; \
130 output_row[2] = row[j * sizeof(uint32_t)] & 0xff; \
131 if(components == 4) output_row[3] = 0xff; \
135 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 8; \
136 output_row[1] = row[j * sizeof(uint32_t)] & 0xff00; \
137 output_row[2] = (row[j * sizeof(uint32_t)] & 0xff) << 8; \
138 if(components == 4) output_row[3] = 0xffff; \
140 output_row += components; \
147 void EffectTV::effecttv_to_frame(VFrame *frame, uint32_t *tmp)
149 int width = frame->get_w();
150 int height = frame->get_h();
152 switch(frame->get_color_model())
156 EFFECTTV_TO_FRAME(uint8_t, 3);
161 EFFECTTV_TO_FRAME(uint8_t, 4);
166 EFFECTTV_TO_FRAME(uint16_t, 3);
169 case BC_RGBA16161616:
170 case BC_YUVA16161616:
171 EFFECTTV_TO_FRAME(uint16_t, 4);
178 void EffectTV::image_set_threshold_y(int threshold)
180 y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
185 /* Background image is refreshed every frame */
186 #define IMAGE_BGSUBTRACT_UPDATE_Y(result, \
199 q = (int16_t *)background; \
202 for(i = 0; i < h; i++) \
204 p = (type*)input_rows[j]; \
206 for(j = 0; j < w; j++) \
208 if(is_yuv && sizeof(type) == 2) \
210 R = G = B = (int)p[0] >> 8; \
215 if(is_yuv && sizeof(type) == 1) \
217 R = G = B = (int)p[0]; \
222 if(sizeof(type) == 4) \
224 R = (int)(p[0] * 0x1ff); \
225 G = (int)(p[1] * 0x3ff); \
226 B = (int)(p[2] * 0xff); \
227 CLAMP(R, 0, 0x1ff); \
228 CLAMP(G, 0, 0x3ff); \
232 if(sizeof(type) == 2) \
234 R = (int)p[0] >> (8 - 1); \
235 G = (int)p[1] >> (8 - 2); \
236 B = (int)p[2] >> 8; \
240 R = (int)p[0] << 1; \
241 G = (int)p[1] << 2; \
245 v = (R + G + B) - (int)(*q); \
246 *q = (int16_t)(R + G + B); \
247 *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
264 unsigned char* EffectTV::image_bgsubtract_update_y(unsigned char **input_rows,
265 unsigned char **output_rows,
274 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
281 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
288 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
295 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
302 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
309 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
316 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
323 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
329 case BC_RGBA16161616:
330 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
336 case BC_YUVA16161616:
337 IMAGE_BGSUBTRACT_UPDATE_Y(diff,
353 #define IMAGE_BGSUBTRACT_Y(type, components, is_yuv) \
359 for(i = 0; i < h; i++) \
361 p = (type*)input_rows[i]; \
363 for(j = 0; j < w; j++) \
365 if(is_yuv && sizeof(type) == 2) \
367 R = G = B = (int)p[0] >> 8; \
372 if(is_yuv && sizeof(type) == 1) \
374 R = G = B = (int)p[0]; \
379 if(sizeof(type) == 4) \
381 R = (int)(p[0] * 0x1ff); \
382 G = (int)(p[1] * 0x3ff); \
383 B = (int)(p[2] * 0xff); \
384 CLAMP(R, 0, 0x1ff); \
385 CLAMP(G, 0, 0x3ff); \
389 if(sizeof(type) == 2) \
391 R = (int)p[0] >> (8 - 1); \
392 G = (int)p[1] >> (8 - 2); \
393 B = (int)p[2] >> 8; \
397 R = (int)p[0] << 1; \
398 G = (int)p[1] << 2; \
402 v = (R + G + B) - (int)(*q); \
403 *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
413 unsigned char* EffectTV::image_bgsubtract_y(unsigned char **input_rows,
420 q = (int16_t *)background;
428 IMAGE_BGSUBTRACT_Y(uint8_t, 3, 0);
431 IMAGE_BGSUBTRACT_Y(uint8_t, 3, 1);
434 IMAGE_BGSUBTRACT_Y(float, 3, 0);
437 IMAGE_BGSUBTRACT_Y(float, 4, 0);
440 IMAGE_BGSUBTRACT_Y(uint8_t, 4, 0);
443 IMAGE_BGSUBTRACT_Y(uint8_t, 4, 1);
446 IMAGE_BGSUBTRACT_Y(uint16_t, 3, 0);
449 IMAGE_BGSUBTRACT_Y(uint16_t, 3, 1);
451 case BC_RGBA16161616:
452 IMAGE_BGSUBTRACT_Y(uint16_t, 4, 0);
454 case BC_YUVA16161616:
455 IMAGE_BGSUBTRACT_Y(uint16_t, 4, 1);
466 /* The origin of subtraction function is;
467 * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
469 * This functions is transformed to;
470 * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
472 * (v + threshold)>>24 is 0xff when v is less than -threshold.
473 * (v - threshold)>>24 is 0xff when v is less than threshold.
474 * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
475 * abs(src - dest) > threshold.
484 unsigned char* EffectTV::image_diff_filter(unsigned char *diff)
487 unsigned char *src, *dest;
489 unsigned int sum1, sum2, sum3;
494 dest = diff2 + width + 1;
495 for(y = 1; y < height - 1; y++)
497 sum1 = src[0] + src[width] + src[width * 2];
498 sum2 = src[1] + src[width + 1] + src[width * 2 + 1];
501 for(x = 1; x < width - 1; x++)
503 sum3 = src[0] + src[width] + src[width * 2];
504 count = sum1 + sum2 + sum3;
507 *dest++ = (0xff * 3 - count) >> 24;
522 #define IMAGE_BGSET_Y(type, components, is_yuv) \
528 int width = frame->get_w(); \
529 int height = frame->get_h(); \
531 q = (int16_t *)background; \
535 for(i = 0; i < height; i++) \
537 p = (type*)frame->get_rows()[i]; \
539 for(j = 0; j < width; j++) \
541 if(is_yuv && sizeof(type) == 2) \
543 R = G = B = (int)p[0] >> 8; \
548 if(is_yuv && sizeof(type) == 1) \
550 R = G = B = (int)p[0]; \
555 if(sizeof(type) == 4) \
557 R = (int)(p[0] * 0x1ff); \
558 G = (int)(p[1] * 0x3ff); \
559 B = (int)(p[2] * 0xff); \
560 CLAMP(R, 0, 0x1ff); \
561 CLAMP(G, 0, 0x3ff); \
565 if(sizeof(type) == 2) \
567 R = (int)p[0] >> (8 - 1); \
568 G = (int)p[1] >> (8 - 2); \
569 B = (int)p[2] >> 8; \
573 R = (int)p[0] << 1; \
574 G = (int)p[1] << 2; \
578 *q = (int16_t)(R + G + B); \
591 void EffectTV::image_bgset_y(VFrame *frame)
593 switch(frame->get_color_model())
596 IMAGE_BGSET_Y(uint8_t, 3, 0);
599 IMAGE_BGSET_Y(float, 3, 0);
602 IMAGE_BGSET_Y(uint8_t, 3, 1);
605 IMAGE_BGSET_Y(uint8_t, 3, 0);
608 IMAGE_BGSET_Y(float, 3, 0);
611 IMAGE_BGSET_Y(uint8_t, 3, 1);
614 IMAGE_BGSET_Y(uint16_t, 3, 0);
617 IMAGE_BGSET_Y(uint16_t, 3, 1);
619 case BC_RGBA16161616:
620 IMAGE_BGSET_Y(uint16_t, 4, 0);
622 case BC_YUVA16161616:
623 IMAGE_BGSET_Y(uint16_t, 4, 1);