r1053: Add Russian translation.
[cinelerra_cv.git] / plugins / libeffecttv / effecttv.C
blob23b01f9a45f70fce1588fd34c3452707dfd9347b
1 #include "colormodels.h"
2 #include "effecttv.h"
3 #include "plugincolors.h"
4 #include "vframe.h"
6 #include <stdint.h> 
7 #include <stdio.h>
11 unsigned int EffectTV::fastrand_val = 0;
13 EffectTV::EffectTV(int w, int h)
15         this->w = w;
16         this->h = h;
17         background = (unsigned char*)new uint16_t[w * h];
18         diff = new unsigned char[w * h];
19         diff2 = new unsigned char[w * h];
20         yuv_init();
21         yuv = new YUV;
24 EffectTV::~EffectTV()
26         delete [] background;
27         delete [] diff;
28         delete [] diff2;
29         delete yuv;
33 int EffectTV::yuv_init()
35         int i;
37         for(i = 0; i < 256; i++)
38         {
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]);
53         }
54         return 0;
58 #define FRAME_TO_EFFECTTV(type, components) \
59 { \
60         for(int i = 0; i < width; i++) \
61         { \
62                 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
63                 type *input_row = ((type**)frame->get_rows())[i]; \
64  \
65                 for(int j = 0; j < width; j++) \
66                 { \
67                         if(sizeof(type) == 1) \
68                         { \
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]; \
72                         } \
73                         else \
74                         { \
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; \
78                         } \
79                         input_row += components; \
80                         row++; \
81                 } \
82         } \
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())
92         {
93                 case BC_RGB888:
94                 case BC_YUV888:
95                         FRAME_TO_EFFECTTV(uint8_t, 3);
96                         break;
97                 
98                 case BC_RGBA8888:
99                 case BC_YUVA8888:
100                         FRAME_TO_EFFECTTV(uint8_t, 4);
101                         break;
103                 case BC_RGB161616:
104                 case BC_YUV161616:
105                         FRAME_TO_EFFECTTV(uint16_t, 3);
106                         break;
107                 
108                 case BC_RGBA16161616:
109                 case BC_YUVA16161616:
110                         FRAME_TO_EFFECTTV(uint16_t, 4);
111                         break;
112         }
117 #define EFFECTTV_TO_FRAME(type, components) \
118 { \
119         for(int i = 0; i < width; i++) \
120         { \
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++) \
125                 { \
126                         if(sizeof(type) == 1) \
127                         { \
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; \
132                         } \
133                         else \
134                         { \
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; \
139                         } \
140                         output_row += components; \
141                         row++; \
142                 } \
143         } \
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())
153         {
154                 case BC_RGB888:
155                 case BC_YUV888:
156                         EFFECTTV_TO_FRAME(uint8_t, 3);
157                         break;
158                 
159                 case BC_RGBA8888:
160                 case BC_YUVA8888:
161                         EFFECTTV_TO_FRAME(uint8_t, 4);
162                         break;
164                 case BC_RGB161616:
165                 case BC_YUV161616:
166                         EFFECTTV_TO_FRAME(uint16_t, 3);
167                         break;
168                 
169                 case BC_RGBA16161616:
170                 case BC_YUVA16161616:
171                         EFFECTTV_TO_FRAME(uint16_t, 4);
172                         break;
173         }
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, \
187         input_rows,  \
188         type,  \
189         components, \
190         is_yuv) \
191 { \
192         int i, j; \
193         int R, G, B; \
194         type *p; \
195         int16_t *q; \
196         unsigned char *r; \
197         int v; \
199         q = (int16_t *)background; \
200         r = diff; \
202         for(i = 0; i < h; i++)  \
203         { \
204                 p = (type*)input_rows[j]; \
206                 for(j = 0; j < w; j++) \
207                 { \
208                         if(is_yuv && sizeof(type) == 2) \
209                         { \
210                                 R = G = B = (int)p[0] >> 8; \
211                                 R <<= 1; \
212                                 G <<= 2; \
213                         } \
214                         else \
215                         if(is_yuv && sizeof(type) == 1) \
216                         { \
217                                 R = G = B = (int)p[0]; \
218                                 R <<= 1; \
219                                 G <<= 2; \
220                         } \
221                         else \
222                         if(sizeof(type) == 4) \
223                         { \
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); \
229                                 CLAMP(B, 0, 0xff); \
230                         } \
231                         else \
232                         if(sizeof(type) == 2) \
233                         { \
234                                 R = (int)p[0] >> (8 - 1); \
235                                 G = (int)p[1] >> (8 - 2); \
236                                 B = (int)p[2] >> 8; \
237                         } \
238                         else \
239                         { \
240                                 R = (int)p[0] << 1; \
241                                 G = (int)p[1] << 2; \
242                                 B = (int)p[2]; \
243                         } \
245                         v = (R + G + B) - (int)(*q); \
246                         *q = (int16_t)(R + G + B); \
247                         *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
249                         p += components; \
250                         q++; \
251                         r++; \
252                 } \
253         } \
255         result = diff; \
264 unsigned char* EffectTV::image_bgsubtract_update_y(unsigned char **input_rows, 
265         unsigned char **output_rows, 
266         int color_model)
268         unsigned char *diff;
271         switch(color_model)
272         {
273                 case BC_RGB888:
274                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
275                                 input_rows, 
276                                 uint8_t, 
277                                 3,
278                                 0);
279                         break;
280                 case BC_YUV888:
281                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
282                                 input_rows, 
283                                 uint8_t, 
284                                 3,
285                                 1);
286                         break;
287                 case BC_RGB_FLOAT:
288                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
289                                 input_rows, 
290                                 float, 
291                                 3,
292                                 0);
293                         break;
294                 case BC_RGBA8888:
295                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
296                                 input_rows, 
297                                 uint8_t, 
298                                 4,
299                                 0);
300                         break;
301                 case BC_RGBA_FLOAT:
302                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
303                                 input_rows, 
304                                 float, 
305                                 4,
306                                 0);
307                         break;
308                 case BC_YUVA8888:
309                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
310                                 input_rows, 
311                                 uint8_t, 
312                                 4,
313                                 1);
314                         break;
315                 case BC_RGB161616:
316                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
317                                 input_rows, 
318                                 uint16_t, 
319                                 3,
320                                 0);
321                         break;
322                 case BC_YUV161616:
323                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
324                                 input_rows, 
325                                 uint16_t, 
326                                 3,
327                                 1);
328                         break;
329                 case BC_RGBA16161616:
330                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
331                                 input_rows, 
332                                 uint16_t, 
333                                 4,
334                                 0);
335                         break;
336                 case BC_YUVA16161616:
337                         IMAGE_BGSUBTRACT_UPDATE_Y(diff, 
338                                 input_rows, 
339                                 uint16_t, 
340                                 4,
341                                 1);
342                         break;
343         }
344         
345         return diff;
353 #define IMAGE_BGSUBTRACT_Y(type, components, is_yuv) \
354 { \
355         int i, j; \
356         int R, G, B; \
357         type *p; \
359         for(i = 0; i < h; i++) \
360         { \
361                 p = (type*)input_rows[i]; \
363                 for(j = 0; j < w; j++) \
364                 { \
365                         if(is_yuv && sizeof(type) == 2) \
366                         { \
367                                 R = G = B = (int)p[0] >> 8; \
368                                 R <<= 1; \
369                                 G <<= 2; \
370                         } \
371                         else \
372                         if(is_yuv && sizeof(type) == 1) \
373                         { \
374                                 R = G = B = (int)p[0]; \
375                                 R <<= 1; \
376                                 G <<= 2; \
377                         } \
378                         else \
379                         if(sizeof(type) == 4) \
380                         { \
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); \
386                                 CLAMP(B, 0, 0xff); \
387                         } \
388                         else \
389                         if(sizeof(type) == 2) \
390                         { \
391                                 R = (int)p[0] >> (8 - 1); \
392                                 G = (int)p[1] >> (8 - 2); \
393                                 B = (int)p[2] >> 8; \
394                         } \
395                         else \
396                         { \
397                                 R = (int)p[0] << 1; \
398                                 G = (int)p[1] << 2; \
399                                 B = (int)p[2]; \
400                         } \
402                         v = (R + G + B) - (int)(*q); \
403                         *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
405                         p += components; \
406                         q++; \
407                         r++; \
408                 } \
409         } \
413 unsigned char* EffectTV::image_bgsubtract_y(unsigned char **input_rows, 
414         int color_model)
416         int16_t *q;
417         unsigned char *r;
418         int v;
420         q = (int16_t *)background;
421         r = diff;
425         switch(color_model)
426         {
427                 case BC_RGB888:
428                         IMAGE_BGSUBTRACT_Y(uint8_t, 3, 0);
429                         break;
430                 case BC_YUV888:
431                         IMAGE_BGSUBTRACT_Y(uint8_t, 3, 1);
432                         break;
433                 case BC_RGB_FLOAT:
434                         IMAGE_BGSUBTRACT_Y(float, 3, 0);
435                         break;
436                 case BC_RGBA_FLOAT:
437                         IMAGE_BGSUBTRACT_Y(float, 4, 0);
438                         break;
439                 case BC_RGBA8888:
440                         IMAGE_BGSUBTRACT_Y(uint8_t, 4, 0);
441                         break;
442                 case BC_YUVA8888:
443                         IMAGE_BGSUBTRACT_Y(uint8_t, 4, 1);
444                         break;
445                 case BC_RGB161616:
446                         IMAGE_BGSUBTRACT_Y(uint16_t, 3, 0);
447                         break;
448                 case BC_YUV161616:
449                         IMAGE_BGSUBTRACT_Y(uint16_t, 3, 1);
450                         break;
451                 case BC_RGBA16161616:
452                         IMAGE_BGSUBTRACT_Y(uint16_t, 4, 0);
453                         break;
454                 case BC_YUVA16161616:
455                         IMAGE_BGSUBTRACT_Y(uint16_t, 4, 1);
456                         break;
457         }
461         return diff;
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.
476  */
484 unsigned char* EffectTV::image_diff_filter(unsigned char *diff)
486         int x, y;
487         unsigned char *src, *dest;
488         unsigned int count;
489         unsigned int sum1, sum2, sum3;
490         int width = w;
491         int height = h;
493         src = diff;
494         dest = diff2 + width + 1;
495         for(y = 1; y < height - 1; y++) 
496         {
497                 sum1 = src[0] + src[width] + src[width * 2];
498                 sum2 = src[1] + src[width + 1] + src[width * 2 + 1];
499                 src += 2;
501                 for(x = 1; x < width - 1; x++) 
502                 {
503                         sum3 = src[0] + src[width] + src[width * 2];
504                         count = sum1 + sum2 + sum3;
505                         sum1 = sum2;
506                         sum2 = sum3;
507                         *dest++ = (0xff * 3 - count) >> 24;
508                         src++;
509                 }
511                 dest += 2;
512         }
514         return diff2;
522 #define IMAGE_BGSET_Y(type, components, is_yuv) \
523 { \
524         int i, j; \
525         int R, G, B; \
526         type *p; \
527         int16_t *q; \
528         int width = frame->get_w(); \
529         int height = frame->get_h(); \
531         q = (int16_t *)background; \
535         for(i = 0; i < height; i++) \
536         { \
537                 p = (type*)frame->get_rows()[i]; \
539                 for(j = 0; j < width; j++) \
540                 { \
541                         if(is_yuv && sizeof(type) == 2) \
542                         { \
543                                 R = G = B = (int)p[0] >> 8; \
544                                 R <<= 1; \
545                                 G <<= 2; \
546                         } \
547                         else \
548                         if(is_yuv && sizeof(type) == 1) \
549                         { \
550                                 R = G = B = (int)p[0]; \
551                                 R <<= 1; \
552                                 G <<= 2; \
553                         } \
554                         else \
555                         if(sizeof(type) == 4) \
556                         { \
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); \
562                                 CLAMP(B, 0, 0xff); \
563                         } \
564                         else \
565                         if(sizeof(type) == 2) \
566                         { \
567                                 R = (int)p[0] >> (8 - 1); \
568                                 G = (int)p[1] >> (8 - 2); \
569                                 B = (int)p[2] >> 8; \
570                         } \
571                         else \
572                         { \
573                                 R = (int)p[0] << 1; \
574                                 G = (int)p[1] << 2; \
575                                 B = (int)p[2]; \
576                         } \
578                         *q = (int16_t)(R + G + B); \
579                         p += components; \
582                         q++; \
583                 } \
584         } \
591 void EffectTV::image_bgset_y(VFrame *frame)
593         switch(frame->get_color_model())
594         {
595                 case BC_RGB888:
596                         IMAGE_BGSET_Y(uint8_t, 3, 0);
597                         break;
598                 case BC_RGB_FLOAT:
599                         IMAGE_BGSET_Y(float, 3, 0);
600                         break;
601                 case BC_YUV888:
602                         IMAGE_BGSET_Y(uint8_t, 3, 1);
603                         break;
604                 case BC_RGBA8888:
605                         IMAGE_BGSET_Y(uint8_t, 3, 0);
606                         break;
607                 case BC_RGBA_FLOAT:
608                         IMAGE_BGSET_Y(float, 3, 0);
609                         break;
610                 case BC_YUVA8888:
611                         IMAGE_BGSET_Y(uint8_t, 3, 1);
612                         break;
613                 case BC_RGB161616:
614                         IMAGE_BGSET_Y(uint16_t, 3, 0);
615                         break;
616                 case BC_YUV161616:
617                         IMAGE_BGSET_Y(uint16_t, 3, 1);
618                         break;
619                 case BC_RGBA16161616:
620                         IMAGE_BGSET_Y(uint16_t, 4, 0);
621                         break;
622                 case BC_YUVA16161616:
623                         IMAGE_BGSET_Y(uint16_t, 4, 1);
624                         break;
625         }