igor ru.po
[goodguy/history.git] / cinelerra-5.1 / plugins / libeffecttv / effecttv.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bccmodels.h"
23 #include "effecttv.h"
24 #include "cicolors.h"
25 #include "vframe.h"
26
27 #include <stdint.h>
28 #include <stdio.h>
29
30
31
32 unsigned int EffectTV::fastrand_val = 0;
33
34 EffectTV::EffectTV(int w, int h)
35 {
36         this->w = w;
37         this->h = h;
38         background = (unsigned char*)new uint16_t[w * h];
39         diff = new unsigned char[w * h];
40         diff2 = new unsigned char[w * h];
41         yuv_init();
42         yuv = new YUV;
43 }
44
45 EffectTV::~EffectTV()
46 {
47         delete [] background;
48         delete [] diff;
49         delete [] diff2;
50         delete yuv;
51 }
52
53
54 int EffectTV::yuv_init()
55 {
56         int i;
57
58         for(i = 0; i < 256; i++)
59         {
60                 YtoRGB[i] =  (int)( 1.164 * (i - 16));
61                 VtoR[i] =        (int)( 1.596 * (i - 128));
62                 VtoG[i] =        (int)(-0.813 * (i - 128));
63                 UtoG[i] =        (int)(-0.391 * (i - 128));
64                 UtoB[i] =        (int)( 2.018 * (i - 128));
65                 RtoY[i] =        (int)( 0.257 * i);
66                 RtoU[i] =        (int)(-0.148 * i);
67                 RtoV[i] =        (int)( 0.439 * i);
68                 GtoY[i] =        (int)( 0.504 * i);
69                 GtoU[i] =        (int)(-0.291 * i);
70                 GtoV[i] =        (int)(-0.368 * i);
71                 BtoY[i] =        (int)( 0.098 * i);
72                 BtoV[i] =        (int)(-0.071 * i);
73 //printf("EffectTV::yuv_init %d %d %d\n", RtoY[i], GtoY[i], BtoY[i]);
74         }
75         return 0;
76 }
77
78
79 #define FRAME_TO_EFFECTTV(type, components) \
80 { \
81         for(int i = 0; i < width; i++) \
82         { \
83                 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
84                 type *input_row = ((type**)frame->get_rows())[i]; \
85  \
86                 for(int j = 0; j < width; j++) \
87                 { \
88                         if(sizeof(type) == 1) \
89                         { \
90                                 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 16; \
91                                 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]) << 8; \
92                                 row[j * sizeof(uint32_t)] |= input_row[2]; \
93                         } \
94                         else \
95                         { \
96                                 row[j * sizeof(uint32_t)] = ((uint32_t)input_row[0]) << 8; \
97                                 row[j * sizeof(uint32_t)] |= ((uint32_t)input_row[1]); \
98                                 row[j * sizeof(uint32_t)] |= input_row[2] >> 8; \
99                         } \
100                         input_row += components; \
101                         row++; \
102                 } \
103         } \
104 }
105
106
107 void EffectTV::frame_to_effecttv(VFrame *frame, uint32_t *tmp)
108 {
109         int width = frame->get_w();
110         //int height = frame->get_h();
111
112         switch(frame->get_color_model())
113         {
114                 case BC_RGB888:
115                 case BC_YUV888:
116                         FRAME_TO_EFFECTTV(uint8_t, 3);
117                         break;
118
119                 case BC_RGBA8888:
120                 case BC_YUVA8888:
121                         FRAME_TO_EFFECTTV(uint8_t, 4);
122                         break;
123
124                 case BC_RGB161616:
125                 case BC_YUV161616:
126                         FRAME_TO_EFFECTTV(uint16_t, 3);
127                         break;
128
129                 case BC_RGBA16161616:
130                 case BC_YUVA16161616:
131                         FRAME_TO_EFFECTTV(uint16_t, 4);
132                         break;
133         }
134 }
135
136
137
138 #define EFFECTTV_TO_FRAME(type, components, alpha) \
139 { \
140         for(int i = 0; i < width; i++) \
141         { \
142                 uint32_t *row = tmp + i * width * sizeof(uint32_t); \
143                 type *output_row = ((type**)frame->get_rows())[i]; \
144  \
145                 for(int j = 0; j < width; j++) \
146                 { \
147                         if(sizeof(type) == 1) \
148                         { \
149                                 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 16; \
150                                 output_row[1] = (row[j * sizeof(uint32_t)] & 0xff00) >> 8; \
151                                 output_row[2] = row[j * sizeof(uint32_t)] & 0xff; \
152                                 if(components == 4) output_row[3] = alpha; \
153                         } \
154                         else \
155                         { \
156                                 output_row[0] = (row[j * sizeof(uint32_t)] & 0xff0000) >> 8; \
157                                 output_row[1] = row[j * sizeof(uint32_t)] & 0xff00; \
158                                 output_row[2] = (row[j * sizeof(uint32_t)] & 0xff) << 8; \
159                                 if(components == 4) output_row[3] = alpha; \
160                         } \
161                         output_row += components; \
162                         row++; \
163                 } \
164         } \
165 }
166
167
168 void EffectTV::effecttv_to_frame(VFrame *frame, uint32_t *tmp)
169 {
170         int width = frame->get_w();
171         //int height = frame->get_h();
172
173         switch(frame->get_color_model())
174         {
175                 case BC_RGB888:
176                 case BC_YUV888:
177                         EFFECTTV_TO_FRAME(uint8_t, 3, 0xff);
178                         break;
179
180                 case BC_RGBA8888:
181                 case BC_YUVA8888:
182                         EFFECTTV_TO_FRAME(uint8_t, 4, 0xff);
183                         break;
184
185                 case BC_RGB161616:
186                 case BC_YUV161616:
187                         EFFECTTV_TO_FRAME(uint16_t, 3, 0xffff);
188                         break;
189
190                 case BC_RGBA16161616:
191                 case BC_YUVA16161616:
192                         EFFECTTV_TO_FRAME(uint16_t, 4, 0xffff);
193                         break;
194         }
195 }
196
197
198
199 void EffectTV::image_set_threshold_y(int threshold)
200 {
201         y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
202 }
203
204
205
206 /* Background image is refreshed every frame */
207 #define \
208 IMAGE_BGSUBTRACT_UPDATE_Y(type, components, is_yuv) \
209 { \
210         int i, j; \
211         int R, G, B; \
212         type *p; \
213         int16_t *q; \
214         unsigned char *r; \
215         int v; \
216  \
217         q = (int16_t *)background; \
218         r = diff; \
219  \
220         for(i = 0; i < h; i++)  \
221         { \
222                 p = (type*)input_rows[i]; \
223  \
224                 for(j = 0; j < w; j++) \
225                 { \
226                         if(is_yuv && sizeof(type) == 2) \
227                         { \
228                                 R = G = B = (int)p[0] >> 8; \
229                                 R <<= 1; \
230                                 G <<= 2; \
231                         } \
232                         else \
233                         if(is_yuv && sizeof(type) == 1) \
234                         { \
235                                 R = G = B = (int)p[0]; \
236                                 R <<= 1; \
237                                 G <<= 2; \
238                         } \
239                         else \
240                         if(sizeof(type) == 4) \
241                         { \
242                                 R = (int)(p[0] * 0x1ff); \
243                                 G = (int)(p[1] * 0x3ff); \
244                                 B = (int)(p[2] * 0xff); \
245                                 CLAMP(R, 0, 0x1ff); \
246                                 CLAMP(G, 0, 0x3ff); \
247                                 CLAMP(B, 0, 0xff); \
248                         } \
249                         else \
250                         if(sizeof(type) == 2) \
251                         { \
252                                 R = (int)p[0] >> (8 - 1); \
253                                 G = (int)p[1] >> (8 - 2); \
254                                 B = (int)p[2] >> 8; \
255                         } \
256                         else \
257                         { \
258                                 R = (int)p[0] << 1; \
259                                 G = (int)p[1] << 2; \
260                                 B = (int)p[2]; \
261                         } \
262  \
263                         v = (R + G + B) - (int)(*q); \
264                         *q = (int16_t)(R + G + B); \
265                         *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
266  \
267                         p += components; \
268                         q++; \
269                         r++; \
270                 } \
271         } \
272 }
273
274
275
276
277
278
279
280 unsigned char* EffectTV::image_bgsubtract_update_y(unsigned char **input_rows,
281         unsigned char **output_rows,
282         int color_model)
283 {
284         switch(color_model)
285         {
286                 case BC_RGB888:
287                         IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 3, 0);
288                         break;
289                 case BC_YUV888:
290                         IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 3, 1);
291                         break;
292                 case BC_RGB_FLOAT:
293                         IMAGE_BGSUBTRACT_UPDATE_Y(float, 3, 0);
294                         break;
295                 case BC_RGBA8888:
296                         IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 4, 0);
297                         break;
298                 case BC_RGBA_FLOAT:
299                         IMAGE_BGSUBTRACT_UPDATE_Y(float, 4, 0);
300                         break;
301                 case BC_YUVA8888:
302                         IMAGE_BGSUBTRACT_UPDATE_Y(uint8_t, 4, 1);
303                         break;
304                 case BC_RGB161616:
305                         IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 3, 0);
306                         break;
307                 case BC_YUV161616:
308                         IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 3, 1);
309                         break;
310                 case BC_RGBA16161616:
311                         IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 4, 0);
312                         break;
313                 case BC_YUVA16161616:
314                         IMAGE_BGSUBTRACT_UPDATE_Y(uint16_t, 4, 1);
315                         break;
316         }
317
318         return diff;
319 }
320
321
322
323
324
325
326 #define IMAGE_BGSUBTRACT_Y(type, components, is_yuv) \
327 { \
328         int i, j; \
329         int R, G, B; \
330         type *p; \
331  \
332         for(i = 0; i < h; i++) \
333         { \
334                 p = (type*)input_rows[i]; \
335  \
336                 for(j = 0; j < w; j++) \
337                 { \
338                         if(is_yuv && sizeof(type) == 2) \
339                         { \
340                                 R = G = B = (int)p[0] >> 8; \
341                                 R <<= 1; \
342                                 G <<= 2; \
343                         } \
344                         else \
345                         if(is_yuv && sizeof(type) == 1) \
346                         { \
347                                 R = G = B = (int)p[0]; \
348                                 R <<= 1; \
349                                 G <<= 2; \
350                         } \
351                         else \
352                         if(sizeof(type) == 4) \
353                         { \
354                                 R = (int)(p[0] * 0x1ff); \
355                                 G = (int)(p[1] * 0x3ff); \
356                                 B = (int)(p[2] * 0xff); \
357                                 CLAMP(R, 0, 0x1ff); \
358                                 CLAMP(G, 0, 0x3ff); \
359                                 CLAMP(B, 0, 0xff); \
360                         } \
361                         else \
362                         if(sizeof(type) == 2) \
363                         { \
364                                 R = (int)p[0] >> (8 - 1); \
365                                 G = (int)p[1] >> (8 - 2); \
366                                 B = (int)p[2] >> 8; \
367                         } \
368                         else \
369                         { \
370                                 R = (int)p[0] << 1; \
371                                 G = (int)p[1] << 2; \
372                                 B = (int)p[2]; \
373                         } \
374  \
375                         v = (R + G + B) - (int)(*q); \
376                         *r = ((v + y_threshold) >> 24) | ((y_threshold - v) >> 24); \
377  \
378                         p += components; \
379                         q++; \
380                         r++; \
381                 } \
382         } \
383 }
384
385
386 unsigned char* EffectTV::image_bgsubtract_y(unsigned char **input_rows,
387         int color_model)
388 {
389         int16_t *q;
390         unsigned char *r;
391         int v;
392
393         q = (int16_t *)background;
394         r = diff;
395
396
397
398         switch(color_model)
399         {
400                 case BC_RGB888:
401                         IMAGE_BGSUBTRACT_Y(uint8_t, 3, 0);
402                         break;
403                 case BC_YUV888:
404                         IMAGE_BGSUBTRACT_Y(uint8_t, 3, 1);
405                         break;
406                 case BC_RGB_FLOAT:
407                         IMAGE_BGSUBTRACT_Y(float, 3, 0);
408                         break;
409                 case BC_RGBA_FLOAT:
410                         IMAGE_BGSUBTRACT_Y(float, 4, 0);
411                         break;
412                 case BC_RGBA8888:
413                         IMAGE_BGSUBTRACT_Y(uint8_t, 4, 0);
414                         break;
415                 case BC_YUVA8888:
416                         IMAGE_BGSUBTRACT_Y(uint8_t, 4, 1);
417                         break;
418                 case BC_RGB161616:
419                         IMAGE_BGSUBTRACT_Y(uint16_t, 3, 0);
420                         break;
421                 case BC_YUV161616:
422                         IMAGE_BGSUBTRACT_Y(uint16_t, 3, 1);
423                         break;
424                 case BC_RGBA16161616:
425                         IMAGE_BGSUBTRACT_Y(uint16_t, 4, 0);
426                         break;
427                 case BC_YUVA16161616:
428                         IMAGE_BGSUBTRACT_Y(uint16_t, 4, 1);
429                         break;
430         }
431
432
433
434         return diff;
435
436
437
438
439 /* The origin of subtraction function is;
440  * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
441  *
442  * This functions is transformed to;
443  * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
444  *
445  * (v + threshold)>>24 is 0xff when v is less than -threshold.
446  * (v - threshold)>>24 is 0xff when v is less than threshold.
447  * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
448  * abs(src - dest) > threshold.
449  */
450 }
451
452
453
454
455
456
457 unsigned char* EffectTV::image_diff_filter(unsigned char *diff)
458 {
459         int x, y;
460         unsigned char *src, *dest;
461         unsigned int count;
462         unsigned int sum1, sum2, sum3;
463         int width = w;
464         int height = h;
465
466         src = diff;
467         dest = diff2 + width + 1;
468         for(y = 1; y < height - 1; y++)
469         {
470                 sum1 = src[0] + src[width] + src[width * 2];
471                 sum2 = src[1] + src[width + 1] + src[width * 2 + 1];
472                 src += 2;
473
474                 for(x = 1; x < width - 1; x++)
475                 {
476                         sum3 = src[0] + src[width] + src[width * 2];
477                         count = sum1 + sum2 + sum3;
478                         sum1 = sum2;
479                         sum2 = sum3;
480                         *dest++ = (0xff * 3 - count) >> 24;
481                         src++;
482                 }
483
484                 dest += 2;
485         }
486
487         return diff2;
488 }
489
490
491
492
493
494
495 #define IMAGE_BGSET_Y(type, components, is_yuv) \
496 { \
497         int i, j; \
498         int R, G, B; \
499         type *p; \
500         int16_t *q; \
501         int width = frame->get_w(); \
502         int height = frame->get_h(); \
503  \
504         q = (int16_t *)background; \
505  \
506  \
507  \
508         for(i = 0; i < height; i++) \
509         { \
510                 p = (type*)frame->get_rows()[i]; \
511  \
512                 for(j = 0; j < width; j++) \
513                 { \
514                         if(is_yuv && sizeof(type) == 2) \
515                         { \
516                                 R = G = B = (int)p[0] >> 8; \
517                                 R <<= 1; \
518                                 G <<= 2; \
519                         } \
520                         else \
521                         if(is_yuv && sizeof(type) == 1) \
522                         { \
523                                 R = G = B = (int)p[0]; \
524                                 R <<= 1; \
525                                 G <<= 2; \
526                         } \
527                         else \
528                         if(sizeof(type) == 4) \
529                         { \
530                                 R = (int)(p[0] * 0x1ff); \
531                                 G = (int)(p[1] * 0x3ff); \
532                                 B = (int)(p[2] * 0xff); \
533                                 CLAMP(R, 0, 0x1ff); \
534                                 CLAMP(G, 0, 0x3ff); \
535                                 CLAMP(B, 0, 0xff); \
536                         } \
537                         else \
538                         if(sizeof(type) == 2) \
539                         { \
540                                 R = (int)p[0] >> (8 - 1); \
541                                 G = (int)p[1] >> (8 - 2); \
542                                 B = (int)p[2] >> 8; \
543                         } \
544                         else \
545                         { \
546                                 R = (int)p[0] << 1; \
547                                 G = (int)p[1] << 2; \
548                                 B = (int)p[2]; \
549                         } \
550  \
551                         *q = (int16_t)(R + G + B); \
552                         p += components; \
553  \
554  \
555                         q++; \
556                 } \
557         } \
558 }
559
560
561
562
563
564 void EffectTV::image_bgset_y(VFrame *frame)
565 {
566         switch(frame->get_color_model())
567         {
568                 case BC_RGB888:
569                         IMAGE_BGSET_Y(uint8_t, 3, 0);
570                         break;
571                 case BC_RGB_FLOAT:
572                         IMAGE_BGSET_Y(float, 3, 0);
573                         break;
574                 case BC_YUV888:
575                         IMAGE_BGSET_Y(uint8_t, 3, 1);
576                         break;
577                 case BC_RGBA8888:
578                         IMAGE_BGSET_Y(uint8_t, 3, 0);
579                         break;
580                 case BC_RGBA_FLOAT:
581                         IMAGE_BGSET_Y(float, 3, 0);
582                         break;
583                 case BC_YUVA8888:
584                         IMAGE_BGSET_Y(uint8_t, 3, 1);
585                         break;
586                 case BC_RGB161616:
587                         IMAGE_BGSET_Y(uint16_t, 3, 0);
588                         break;
589                 case BC_YUV161616:
590                         IMAGE_BGSET_Y(uint16_t, 3, 1);
591                         break;
592                 case BC_RGBA16161616:
593                         IMAGE_BGSET_Y(uint16_t, 4, 0);
594                         break;
595                 case BC_YUVA16161616:
596                         IMAGE_BGSET_Y(uint16_t, 4, 1);
597                         break;
598         }
599 }
600
601