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