r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / burn / effecttv.C
blobecf7ec30dfaeb7060b4e570ed476446d159fd995
1 #include "colormodels.h"
2 #include "effecttv.h"
3 #include "vframe.h"
5 #include <stdint.h> 
6 #include <stdio.h>
10 unsigned int EffectTV::fastrand_val = 0;
12 EffectTV::EffectTV(int w, int h)
14         this->w = w;
15         this->h = h;
16         background = (unsigned char*)new uint16_t[w * h];
17         diff = new unsigned char[w * h];
18         diff2 = new unsigned char[w * h];
19         yuv_init();
22 EffectTV::~EffectTV()
24         delete [] background;
25         delete [] diff;
26         delete [] diff2;
30 int EffectTV::yuv_init()
32         int i;
34         for(i = 0; i < 256; i++)
35         {
36                 YtoRGB[i] =  (int)( 1.164 * (i - 16));
37                 VtoR[i] =        (int)( 1.596 * (i - 128));
38                 VtoG[i] =        (int)(-0.813 * (i - 128));
39                 UtoG[i] =        (int)(-0.391 * (i - 128));
40                 UtoB[i] =        (int)( 2.018 * (i - 128));
41                 RtoY[i] =        (int)( 0.257 * i);
42                 RtoU[i] =        (int)(-0.148 * i);
43                 RtoV[i] =        (int)( 0.439 * i);
44                 GtoY[i] =        (int)( 0.504 * i);
45                 GtoU[i] =        (int)(-0.291 * i);
46                 GtoV[i] =        (int)(-0.368 * i);
47                 BtoY[i] =        (int)( 0.098 * i);
48                 BtoV[i] =        (int)(-0.071 * i);
49 //printf("EffectTV::yuv_init %d %d %d\n", RtoY[i], GtoY[i], BtoY[i]);
50         }
51         return 0;
55 #define FRAME_TO_EFFECTTV(type, components) \
56 { \
57         for(int i = 0; i < width; i++) \
58         { \
59                 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
60                 type *input_row = ((type**)frame->get_rows())[i]; \
61  \
62                 for(int j = 0; j < width; j++) \
63                 { \
64                         if(sizeof(type) == 1) \
65                         { \
66                                 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 16; \
67                                 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]) << 8; \
68                                 row[j * sizeof(uint32_t)] |= input_row[2]; \
69                         } \
70                         else \
71                         { \
72                                 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 8; \
73                                 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]); \
74                                 row[j * sizeof(uint32_t)] |= input_row[2] >> 8; \
75                         } \
76                         input_row += components; \
77                         row++; \
78                 } \
79         } \
83 void EffectTV::frame_to_effecttv(VFrame *frame, uint32_t *tmp)
85         int width = frame->get_w();
86         int height = frame->get_h();
88         switch(frame->get_color_model())
89         {
90                 case BC_RGB888:
91                 case BC_YUV888:
92                         FRAME_TO_EFFECTTV(uint8_t, 3);
93                         break;
94                 
95                 case BC_RGBA8888:
96                 case BC_YUVA8888:
97                         FRAME_TO_EFFECTTV(uint8_t, 4);
98                         break;
100                 case BC_RGB161616:
101                 case BC_YUV161616:
102                         FRAME_TO_EFFECTTV(uint16_t, 3);
103                         break;
104                 
105                 case BC_RGBA16161616:
106                 case BC_YUVA16161616:
107                         FRAME_TO_EFFECTTV(uint16_t, 4);
108                         break;
109         }
114 #define EFFECTTV_TO_FRAME(type, components) \
115 { \
116         for(int i = 0; i < width; i++) \
117         { \
118                 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
119                 type *output_row = ((type**)frame->get_rows())[i]; \
121                 for(int j = 0; j < width; j++) \
122                 { \
123                         if(sizeof(type) == 1) \
124                         { \
125                                 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 16; \
126                                 output_row[1] = (row[j * sizeof(uint32_t)] & 0xff00) >> 8; \
127                                 output_row[2] = row[j * sizeof(uint32_t)] & 0xff; \
128                                 if(components == 4) output_row[3] = 0xff; \
129                         } \
130                         else \
131                         { \
132                                 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 8; \
133                                 output_row[1] = row[j * sizeof(uint32_t)] & 0xff00; \
134                                 output_row[2] = (row[j * sizeof(uint32_t)] & 0xff) << 8; \
135                                 if(components == 4) output_row[3] = 0xffff; \
136                         } \
137                         output_row += components; \
138                         row++; \
139                 } \
140         } \
144 void EffectTV::effecttv_to_frame(VFrame *frame, uint32_t *tmp)
146         int width = frame->get_w();
147         int height = frame->get_h();
149         switch(frame->get_color_model())
150         {
151                 case BC_RGB888:
152                 case BC_YUV888:
153                         EFFECTTV_TO_FRAME(uint8_t, 3);
154                         break;
155                 
156                 case BC_RGBA8888:
157                 case BC_YUVA8888:
158                         EFFECTTV_TO_FRAME(uint8_t, 4);
159                         break;
161                 case BC_RGB161616:
162                 case BC_YUV161616:
163                         EFFECTTV_TO_FRAME(uint16_t, 3);
164                         break;
165                 
166                 case BC_RGBA16161616:
167                 case BC_YUVA16161616:
168                         EFFECTTV_TO_FRAME(uint16_t, 4);
169                         break;
170         }
175 void EffectTV::image_set_threshold_y(int threshold)
177         y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
182 /* Background image is refreshed every frame */
183 #define IMAGE_BGSUBTRACT_UPDATE_Y(result, \
184         input_rows,  \
185         type,  \
186         components) \
187 { \
188         int i, j; \
189         int R, G, B; \
190         type *p; \
191         int16_t *q; \
192         unsigned char *r; \
193         int v; \
195         q = (int16_t *)background; \
196         r = diff; \
198         for(i = 0; i < h; i++)  \
199         { \
200                 p = (type*)input_rows[j]; \
202                 for(j = 0; j < w; j++) \
203                 { \
204                         if(sizeof(type) == 2) \
205                         { \
206                                 R = p[0] >> (8 - 1); \
207                                 G = p[1] >> (8 - 2); \
208                                 B = p[2] >> 8; \
209                         } \
210                         else \
211                         { \
212                                 R = p[0] << 1; \
213                                 G = p[1] << 2; \
214                                 B = p[2]; \
215                         } \
217                         v = (R + G + B) - (int)(*q); \
218                         *q = (int16_t)(R + G + B); \
219                         *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
221                         p += components; \
222                         q++; \
223                         r++; \
224                 } \
225         } \
227         result = diff; \
236 unsigned char* EffectTV::image_bgsubtract_update_y(unsigned char **input_rows, 
237         unsigned char **output_rows, 
238         int color_model)
240         unsigned char *diff;
243         switch(color_model)
244         {
245                 case BC_RGB888:
246                 case BC_YUV888:
247                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
248                                 input_rows, 
249                                 uint8_t, 
250                                 3);
251                         break;
252                 case BC_RGBA8888:
253                 case BC_YUVA8888:
254                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
255                                 input_rows, 
256                                 uint8_t, 
257                                 4);
258                         break;
259                 case BC_RGB161616:
260                 case BC_YUV161616:
261                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
262                                 input_rows, 
263                                 uint16_t, 
264                                 3);
265                         break;
266                 case BC_RGBA16161616:
267                 case BC_YUVA16161616:
268                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
269                                 input_rows, 
270                                 uint16_t, 
271                                 4);
272                         break;
273         }
274         
275         return diff;
283 #define IMAGE_BGSUBTRACT_Y(type, components) \
284 { \
285         int i, j; \
286         int R, G, B; \
287         type *p; \
289         for(i = 0; i < h; i++) \
290         { \
291                 p = (type*)input_rows[i]; \
293                 for(j = 0; j < w; j++) \
294                 { \
295                         if(sizeof(type) == 2) \
296                         { \
297                                 R = p[0] >> (8 - 1); \
298                                 G = p[1] >> (8 - 2); \
299                                 B = p[2] >> 8; \
300                         } \
301                         else \
302                         { \
303                                 R = p[0] << 1; \
304                                 G = p[1] << 2; \
305                                 B = p[2]; \
306                         } \
308                         v = (R + G + B) - (int)(*q); \
309                         *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
311                         p += components; \
312                         q++; \
313                         r++; \
314                 } \
315         } \
319 unsigned char* EffectTV::image_bgsubtract_y(unsigned char **input_rows, int color_model)
321         int16_t *q;
322         unsigned char *r;
323         int v;
325         q = (int16_t *)background;
326         r = diff;
330         switch(color_model)
331         {
332                 case BC_RGB888:
333                 case BC_YUV888:
334                         IMAGE_BGSUBTRACT_Y(uint8_t, 3);
335                         break;
336                 case BC_RGBA8888:
337                 case BC_YUVA8888:
338                         IMAGE_BGSUBTRACT_Y(uint8_t, 4);
339                         break;
340                 case BC_RGB161616:
341                 case BC_YUV161616:
342                         IMAGE_BGSUBTRACT_Y(uint16_t, 3);
343                         break;
344                 case BC_RGBA16161616:
345                 case BC_YUVA16161616:
346                         IMAGE_BGSUBTRACT_Y(uint16_t, 4);
347                         break;
348         }
352         return diff;
357 /* The origin of subtraction function is;
358  * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
360  * This functions is transformed to;
361  * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
363  * (v + threshold)>>24 is 0xff when v is less than -threshold.
364  * (v - threshold)>>24 is 0xff when v is less than threshold.
365  * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
366  * abs(src - dest) > threshold.
367  */
375 unsigned char* EffectTV::image_diff_filter(unsigned char *diff)
377         int x, y;
378         unsigned char *src, *dest;
379         unsigned int count;
380         unsigned int sum1, sum2, sum3;
381         int width = w;
382         int height = h;
384         src = diff;
385         dest = diff2 + width + 1;
386         for(y = 1; y < height - 1; y++) 
387         {
388                 sum1 = src[0] + src[width] + src[width * 2];
389                 sum2 = src[1] + src[width + 1] + src[width * 2 + 1];
390                 src += 2;
392                 for(x = 1; x < width - 1; x++) 
393                 {
394                         sum3 = src[0] + src[width] + src[width * 2];
395                         count = sum1 + sum2 + sum3;
396                         sum1 = sum2;
397                         sum2 = sum3;
398                         *dest++ = (0xff * 3 - count) >> 24;
399                         src++;
400                 }
402                 dest += 2;
403         }
405         return diff2;
413 #define IMAGE_BGSET_Y(type, components) \
414 { \
415         int i, j; \
416         int R, G, B; \
417         type *p; \
418         int16_t *q; \
419         int width = frame->get_w(); \
420         int height = frame->get_h(); \
422         q = (int16_t *)background; \
426         for(i = 0; i < height; i++) \
427         { \
428                 p = (type*)frame->get_rows()[i]; \
430                 for(j = 0; j < width; j++) \
431                 { \
432                         if(sizeof(type) == 2) \
433                         { \
434                                 R = p[0] >> (8 - 1); \
435                                 G = p[1] >> (8 - 2); \
436                                 B = p[2] >> 8; \
437                         } \
438                         else \
439                         { \
440                                 R = p[0] << 1; \
441                                 G = p[1] << 2; \
442                                 B = p[2]; \
443                         } \
445                         *q = (int16_t)(R + G + B); \
446                         p += components; \
449                         q++; \
450                 } \
451         } \
458 void EffectTV::image_bgset_y(VFrame *frame)
460         switch(frame->get_color_model())
461         {
462                 case BC_RGB888:
463                 case BC_YUV888:
464                         IMAGE_BGSET_Y(uint8_t, 3);
465                         break;
466                 case BC_RGBA8888:
467                 case BC_YUVA8888:
468                         IMAGE_BGSET_Y(uint8_t, 4);
469                         break;
470                 case BC_RGB161616:
471                 case BC_YUV161616:
472                         IMAGE_BGSET_Y(uint16_t, 3);
473                         break;
474                 case BC_RGBA16161616:
475                 case BC_YUVA16161616:
476                         IMAGE_BGSET_Y(uint16_t, 4);
477                         break;
478         }