r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / aging / aging.C
blobc7d2243b115d8ee3e2638ece35aae8f65c7fd6a7
1 #include "clip.h"
2 #include "colormodels.h"
3 #include "filexml.h"
4 #include "picon_png.h"
5 #include "aging.h"
6 #include "agingwindow.h"
7 #include "effecttv.h"
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <unistd.h>
14 #include <libintl.h>
15 #define _(String) gettext(String)
16 #define gettext_noop(String) String
17 #define N_(String) gettext_noop (String)
23 REGISTER_PLUGIN(AgingMain)
30 int AgingConfig::dx[] = { 1, 1, 0, -1, -1, -1,  0, 1};
31 int AgingConfig::dy[] = { 0, -1, -1, -1, 0, 1, 1, 1};
33 AgingConfig::AgingConfig()
35         dust_interval = 0;
36         pits_interval = 0;
37         aging_mode = 0;
38         area_scale = 10;
39         scratch_lines = 7;
40         colorage = 1;
41         scratch = 1;
42         pits = 1;
43         dust = 1;
46 AgingMain::AgingMain(PluginServer *server)
47  : PluginVClient(server)
49         PLUGIN_CONSTRUCTOR_MACRO
50         aging_server = 0;
53 AgingMain::~AgingMain()
55         PLUGIN_DESTRUCTOR_MACRO
56         if(aging_server) delete aging_server;
59 char* AgingMain::plugin_title() { return _("AgingTV"); }
60 int AgingMain::is_realtime() { return 1; }
62 NEW_PICON_MACRO(AgingMain)
64 SHOW_GUI_MACRO(AgingMain, AgingThread)
66 SET_STRING_MACRO(AgingMain)
68 RAISE_WINDOW_MACRO(AgingMain)
70 int AgingMain::load_defaults()
72         return 0;
75 int AgingMain::save_defaults()
77         return 0;
80 void AgingMain::load_configuration()
85 void AgingMain::save_data(KeyFrame *keyframe)
89 void AgingMain::read_data(KeyFrame *keyframe)
94 int AgingMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
96 //printf("AgingMain::process_realtime 1\n");
97         load_configuration();
98 //printf("AgingMain::process_realtime 1\n");
99         this->input_ptr = input_ptr;
100         this->output_ptr = output_ptr;
102         if(!aging_server) aging_server = new AgingServer(this, 
103                 PluginClient::smp + 1, 
104                 PluginClient::smp + 1);
105         aging_server->process_packages();
106 //printf("AgingMain::process_realtime 2\n");
108         return 0;
113 AgingServer::AgingServer(AgingMain *plugin, int total_clients, int total_packages)
114  : LoadServer(1, 1 /* total_clients, total_packages */)
116         this->plugin = plugin;
120 LoadClient* AgingServer::new_client() 
122         return new AgingClient(this);
128 LoadPackage* AgingServer::new_package() 
130         return new AgingPackage; 
135 void AgingServer::init_packages()
137         for(int i = 0; i < total_packages; i++)
138         {
139                 AgingPackage *package = (AgingPackage*)packages[i];
140                 package->row1 = plugin->input_ptr->get_h() / total_packages * i;
141                 package->row2 = package->row1 + plugin->input_ptr->get_h() / total_packages;
142                 if(i >= total_packages - 1)
143                         package->row2 = plugin->input_ptr->get_h();
144         }
154 AgingClient::AgingClient(AgingServer *server)
155  : LoadClient(server)
157         this->plugin = server->plugin;
168 #define COLORAGE(type, components) \
169 { \
170         type a, b; \
171         int i, j, k; \
173         for(i = 0; i < h; i++) \
174         { \
175                 for(j = 0; j < w; j++) \
176                 { \
177                         for(k = 0; k < components; k++) \
178                         { \
179                                 a = ((type**)input_rows)[i][j * components + k]; \
181                                 if(k < 3) \
182                                 { \
183                                         if(sizeof(type) == 2) \
184                                         { \
185                                                 b = (a & 0xffff) >> 2; \
186                                                 ((type**)output_rows)[i][j * components + k] = \
187                                                         a - b + 0x1800 + (EffectTV::fastrand() & 0x1000); \
188                                         } \
189                                         else \
190                                         { \
191                                                 b = (a & 0xff) >> 2; \
192                                                 ((type**)output_rows)[i][j * components + k] =  \
193                                                         a - b + 0x18 + ((EffectTV::fastrand() >> 8) & 0x10); \
194                                         } \
195                                 } \
196                                 else \
197                                 { \
198                                         ((type**)output_rows)[i][j * components + k] = a; \
199                                 } \
200                         } \
201                 } \
202         } \
205 void AgingClient::coloraging(unsigned char **output_rows, 
206         unsigned char **input_rows,
207         int color_model,
208         int w,
209         int h)
211         switch(color_model)
212         {
213                 case BC_RGB888:
214                 case BC_YUV888:
215                         COLORAGE(uint8_t, 3);
216                         break;
217                 
218                 case BC_RGBA8888:
219                 case BC_YUVA8888:
220                         COLORAGE(uint8_t, 4);
221                         break;
222                 
223                 case BC_RGB161616:
224                 case BC_YUV161616:
225                         COLORAGE(uint16_t, 3);
226                         break;
227                 
228                 case BC_RGBA16161616:
229                 case BC_YUVA16161616:
230                         COLORAGE(uint16_t, 4);
231                         break;
232         }
240 #define SCRATCHES(type, components, chroma) \
241 { \
242         int i, j, y, y1, y2; \
243         type *p, a, b; \
244         int w_256 = w * 256; \
246         for(i = 0; i < plugin->config.scratch_lines; i++) \
247         { \
248                 if(plugin->config.scratches[i].life)  \
249                 { \
250                         plugin->config.scratches[i].x = plugin->config.scratches[i].x + plugin->config.scratches[i].dx; \
251                         if(plugin->config.scratches[i].x < 0 || plugin->config.scratches[i].x > w_256)  \
252                         { \
253                                 plugin->config.scratches[i].life = 0; \
254                                 break; \
255                         } \
257                         p = (type*)output_rows[0] + \
258                                 (plugin->config.scratches[i].x >> 8) * \
259                                 components; \
261                         if(plugin->config.scratches[i].init)  \
262                         { \
263                                 y1 = plugin->config.scratches[i].init; \
264                                 plugin->config.scratches[i].init = 0; \
265                         }  \
266                         else  \
267                         { \
268                                 y1 = 0; \
269                         } \
271                         plugin->config.scratches[i].life--; \
272                         if(plugin->config.scratches[i].life)  \
273                         { \
274                                 y2 = h; \
275                         }  \
276                         else  \
277                         { \
278                                 y2 = EffectTV::fastrand() % h; \
279                         } \
281                         for(y = y1; y < y2; y++)  \
282                         { \
283                                 for(j = 0; j < (chroma ? 1 : 3); j++) \
284                                 { \
285                                         if(sizeof(type) == 2) \
286                                         { \
287                                                 a = p[j] & 0xfeff; \
288                                                 a += 0x2000; \
289                                                 b = a & 0x10000; \
290                                                 p[j] = a | (b - (b >> 8)); \
291                                         } \
292                                         else \
293                                         { \
294                                                 a = p[j] & 0xfe; \
295                                                 a += 0x20; \
296                                                 b = a & 0x100; \
297                                                 p[j] = a | (b - (b >> 8)); \
298                                         } \
299                                 } \
301                                 if(chroma) \
302                                 { \
303                                         p[1] = chroma; \
304                                         p[2] = chroma; \
305                                 } \
306                                 p += w * components; \
307                         } \
308                 }  \
309                 else  \
310                 { \
311                         if((EffectTV::fastrand() & 0xf0000000) == 0)  \
312                         { \
313                                 plugin->config.scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
314                                 plugin->config.scratches[i].x = EffectTV::fastrand() % (w_256); \
315                                 plugin->config.scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
316                                 plugin->config.scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
317                         } \
318                 } \
319         } \
324 void AgingClient::scratching(unsigned char **output_rows,
325         int color_model,
326         int w,
327         int h)
329         switch(color_model)
330         {
331                 case BC_RGB888:
332                         SCRATCHES(uint8_t, 3, 0);
333                         break;
335                 case BC_YUV888:
336                         SCRATCHES(uint8_t, 3, 0x80);
337                         break;
338                 
339                 case BC_RGBA8888:
340                         SCRATCHES(uint8_t, 4, 0);
341                         break;
343                 case BC_YUVA8888:
344                         SCRATCHES(uint8_t, 4, 0x80);
345                         break;
346                 
347                 case BC_RGB161616:
348                         SCRATCHES(uint16_t, 3, 0);
349                         break;
351                 case BC_YUV161616:
352                         SCRATCHES(uint16_t, 3, 0x8000);
353                         break;
354                 
355                 case BC_RGBA16161616:
356                         SCRATCHES(uint16_t, 4, 0);
357                         break;
359                 case BC_YUVA16161616:
360                         SCRATCHES(uint16_t, 4, 0x8000);
361                         break;
362         }
367 #define PITS(type, components, chroma) \
368 { \
369         int i, j, k; \
370         int pnum, size, pnumscale; \
371         int x, y; \
373         pnumscale = plugin->config.area_scale * 2; \
375         if(plugin->config.pits_interval)  \
376         { \
377                 pnum = pnumscale + (EffectTV::fastrand() % pnumscale); \
378                 plugin->config.pits_interval--; \
379         }  \
380         else \
381         { \
382                 pnum = EffectTV::fastrand() % pnumscale; \
383                 if((EffectTV::fastrand() & 0xf8000000) == 0)  \
384                 { \
385                         plugin->config.pits_interval = (EffectTV::fastrand() >> 28) + 20; \
386                 } \
387         } \
389         for(i = 0; i < pnum; i++)  \
390         { \
391                 x = EffectTV::fastrand() % (w - 1); \
392                 y = EffectTV::fastrand() % (h - 1); \
394                 size = EffectTV::fastrand() >> 28; \
396                 for(j = 0; j < size; j++)  \
397                 { \
398                         x = x + EffectTV::fastrand() % 3 - 1; \
399                         y = y + EffectTV::fastrand() % 3 - 1; \
401                         CLAMP(x, 0, w - 1); \
402                         CLAMP(y, 0, h - 1); \
403                         for(k = 0; k < (chroma ? 1 : 3); k++) \
404                                 ((type**)output_rows)[y][x * components + k] = 0xc0; \
406             if(chroma) \
407                         { \
408                                 ((type**)output_rows)[y][x * components + 1] = chroma; \
409                                 ((type**)output_rows)[y][x * components + 2] = chroma; \
410                         } \
412                 } \
413         } \
421 void AgingClient::pits(unsigned char **output_rows,
422         int color_model,
423         int w,
424         int h)
426         switch(color_model)
427         {
428                 case BC_RGB888:
429                         PITS(uint8_t, 3, 0);
430                         break;
431                 case BC_YUV888:
432                         PITS(uint8_t, 3, 0x80);
433                         break;
434                 
435                 case BC_RGBA8888:
436                         PITS(uint8_t, 4, 0);
437                         break;
438                 case BC_YUVA8888:
439                         PITS(uint8_t, 4, 0x80);
440                         break;
441                 
442                 case BC_RGB161616:
443                         PITS(uint16_t, 3, 0);
444                         break;
445                 case BC_YUV161616:
446                         PITS(uint16_t, 3, 0x8000);
447                         break;
448                 
449                 case BC_RGBA16161616:
450                         PITS(uint16_t, 4, 0);
451                         break;
452                 case BC_YUVA16161616:
453                         PITS(uint16_t, 4, 0x8000);
454                         break;
455         }
459 #define DUSTS(type, components, chroma) \
460 { \
461         int i, j, k; \
462         int dnum; \
463         int d, len; \
464         int x, y; \
466         if(plugin->config.dust_interval == 0)  \
467         { \
468                 if((EffectTV::fastrand() & 0xf0000000) == 0)  \
469                 { \
470                         plugin->config.dust_interval = EffectTV::fastrand() >> 29; \
471                 } \
472                 return; \
473         } \
475         dnum = plugin->config.area_scale * 4 + (EffectTV::fastrand() >> 27); \
477         for(i = 0; i < dnum; i++)  \
478         { \
479                 x = EffectTV::fastrand() % w; \
480                 y = EffectTV::fastrand() % h; \
481                 d = EffectTV::fastrand() >> 29; \
482                 len = EffectTV::fastrand() % plugin->config.area_scale + 5; \
484                 for(j = 0; j < len; j++)  \
485                 { \
486                         CLAMP(x, 0, w - 1); \
487                         CLAMP(y, 0, h - 1); \
488                         for(k = 0; k < (chroma ? 1 : 3); k++) \
489                                 ((type**)output_rows)[y][x * components + k] = 0x10; \
491                         if(chroma) \
492                         { \
493                                 ((type**)output_rows)[y][x * components + 1] = chroma; \
494                                 ((type**)output_rows)[y][x * components + 2] = chroma; \
495                         } \
497                         y += AgingConfig::dy[d]; \
498                         x += AgingConfig::dx[d]; \
500                         if(x < 0 || x >= w) break; \
501                         if(y < 0 || y >= h) break; \
504                         d = (d + EffectTV::fastrand() % 3 - 1) & 7; \
505                 } \
506         } \
507         plugin->config.dust_interval--; \
513 void AgingClient::dusts(unsigned char **output_rows,
514         int color_model,
515         int w,
516         int h)
518         switch(color_model)
519         {
520                 case BC_RGB888:
521                         DUSTS(uint8_t, 3, 0);
522                         break;
524                 case BC_YUV888:
525                         DUSTS(uint8_t, 3, 0x80);
526                         break;
527                 
528                 case BC_RGBA8888:
529                         DUSTS(uint8_t, 4, 0);
530                         break;
532                 case BC_YUVA8888:
533                         DUSTS(uint8_t, 4, 0x80);
534                         break;
535                 
536                 case BC_RGB161616:
537                         DUSTS(uint16_t, 3, 0);
538                         break;
540                 case BC_YUV161616:
541                         DUSTS(uint16_t, 3, 0x8000);
542                         break;
543                 
544                 case BC_RGBA16161616:
545                         DUSTS(uint16_t, 4, 0);
546                         break;
548                 case BC_YUVA16161616:
549                         DUSTS(uint16_t, 4, 0x8000);
550                         break;
551         }
556 void AgingClient::process_package(LoadPackage *package)
558 //printf("AgingClient::process_package 1\n");
559         AgingPackage *local_package = (AgingPackage*)package;
560         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
561         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
563 //printf("AgingClient::process_package 1\n");
564         if(plugin->config.colorage)
565                 coloraging(output_rows, 
566                         input_rows, 
567                         plugin->input_ptr->get_color_model(), 
568                         plugin->input_ptr->get_w(), 
569                         local_package->row2 - local_package->row1);
570 //printf("AgingClient::process_package 2\n");
571         if(plugin->config.scratch)
572                 scratching(output_rows, 
573                         plugin->input_ptr->get_color_model(), 
574                         plugin->input_ptr->get_w(), 
575                         local_package->row2 - local_package->row1);
576 //printf("AgingClient::process_package 3\n");
577         if(plugin->config.pits)
578                 pits(output_rows, 
579                         plugin->input_ptr->get_color_model(), 
580                         plugin->input_ptr->get_w(), 
581                         local_package->row2 - local_package->row1);
582 //printf("AgingClient::process_package 4 %d\n", plugin->config.dust);
583         if(plugin->config.dust)
584                 dusts(output_rows, 
585                         plugin->input_ptr->get_color_model(), 
586                         plugin->input_ptr->get_w(), 
587                         local_package->row2 - local_package->row1);
588 //printf("AgingClient::process_package 5\n");
593 AgingPackage::AgingPackage()