r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / plugins / aging / aging.C
blob9210bfc203684fcfa38e2eeebc875b650308195a
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 N_("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         int 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 < 3; k++) \
178                         { \
179                                 if(sizeof(type) == 4) \
180                                 { \
181                                         a = (int)(((type**)input_rows)[i][j * components + k] * 0xffff); \
182                                         CLAMP(a, 0, 0xffff); \
183                                 } \
184                                 else \
185                                         a = (int)((type**)input_rows)[i][j * components + k]; \
187                                 if(sizeof(type) == 4) \
188                                 { \
189                                         b = (a & 0xffff) >> 2; \
190                                         ((type**)output_rows)[i][j * components + k] = \
191                                                 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)) / 0xffff; \
192                                 } \
193                                 else \
194                                 if(sizeof(type) == 2) \
195                                 { \
196                                         b = (a & 0xffff) >> 2; \
197                                         ((type**)output_rows)[i][j * components + k] = \
198                                                 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)); \
199                                 } \
200                                 else \
201                                 { \
202                                         b = (a & 0xff) >> 2; \
203                                         ((type**)output_rows)[i][j * components + k] =  \
204                                                 (type)(a - b + 0x18 + ((EffectTV::fastrand() >> 8) & 0x10)); \
205                                 } \
206                         } \
207                 } \
208         } \
211 void AgingClient::coloraging(unsigned char **output_rows, 
212         unsigned char **input_rows,
213         int color_model,
214         int w,
215         int h)
217         switch(color_model)
218         {
219                 case BC_RGB888:
220                 case BC_YUV888:
221                         COLORAGE(uint8_t, 3);
222                         break;
223                 
224                 case BC_RGB_FLOAT:
225                         COLORAGE(float, 3);
226                         break;
227                         
228                 case BC_RGBA_FLOAT:
229                         COLORAGE(float, 4);
230                         break;
231                         
232                 case BC_RGBA8888:
233                 case BC_YUVA8888:
234                         COLORAGE(uint8_t, 4);
235                         break;
236                 
237                 case BC_RGB161616:
238                 case BC_YUV161616:
239                         COLORAGE(uint16_t, 3);
240                         break;
241                 
242                 case BC_RGBA16161616:
243                 case BC_YUVA16161616:
244                         COLORAGE(uint16_t, 4);
245                         break;
246         }
254 #define SCRATCHES(type, components, chroma) \
255 { \
256         int i, j, y, y1, y2; \
257         type *p; \
258         int a, b; \
259         int w_256 = w * 256; \
261         for(i = 0; i < plugin->config.scratch_lines; i++) \
262         { \
263                 if(plugin->config.scratches[i].life)  \
264                 { \
265                         plugin->config.scratches[i].x = plugin->config.scratches[i].x + plugin->config.scratches[i].dx; \
266                         if(plugin->config.scratches[i].x < 0 || plugin->config.scratches[i].x > w_256)  \
267                         { \
268                                 plugin->config.scratches[i].life = 0; \
269                                 break; \
270                         } \
272                         p = (type*)output_rows[0] + \
273                                 (plugin->config.scratches[i].x >> 8) * \
274                                 components; \
276                         if(plugin->config.scratches[i].init)  \
277                         { \
278                                 y1 = plugin->config.scratches[i].init; \
279                                 plugin->config.scratches[i].init = 0; \
280                         }  \
281                         else  \
282                         { \
283                                 y1 = 0; \
284                         } \
286                         plugin->config.scratches[i].life--; \
287                         if(plugin->config.scratches[i].life)  \
288                         { \
289                                 y2 = h; \
290                         }  \
291                         else  \
292                         { \
293                                 y2 = EffectTV::fastrand() % h; \
294                         } \
296                         for(y = y1; y < y2; y++)  \
297                         { \
298                                 for(j = 0; j < (chroma ? 1 : 3); j++) \
299                                 { \
300                                         if(sizeof(type) == 4) \
301                                         { \
302                                                 int temp = (int)(p[j] * 0xffff); \
303                                                 CLAMP(temp, 0, 0xffff); \
304                                                 a = temp & 0xfeff; \
305                                                 a += 0x2000; \
306                                                 b = a & 0x10000; \
307                                                 p[j] = (type)(a | (b - (b >> 8))) / 0xffff; \
308                                         } \
309                                         else \
310                                         if(sizeof(type) == 2) \
311                                         { \
312                                                 int temp = (int)p[j]; \
313                                                 a = temp & 0xfeff; \
314                                                 a += 0x2000; \
315                                                 b = a & 0x10000; \
316                                                 p[j] = (type)(a | (b - (b >> 8))); \
317                                         } \
318                                         else \
319                                         { \
320                                                 int temp = (int)p[j]; \
321                                                 a = temp & 0xfe; \
322                                                 a += 0x20; \
323                                                 b = a & 0x100; \
324                                                 p[j] = (type)(a | (b - (b >> 8))); \
325                                         } \
326                                 } \
328                                 if(chroma) \
329                                 { \
330                                         p[1] = chroma; \
331                                         p[2] = chroma; \
332                                 } \
333                                 p += w * components; \
334                         } \
335                 }  \
336                 else  \
337                 { \
338                         if((EffectTV::fastrand() & 0xf0000000) == 0)  \
339                         { \
340                                 plugin->config.scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
341                                 plugin->config.scratches[i].x = EffectTV::fastrand() % (w_256); \
342                                 plugin->config.scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
343                                 plugin->config.scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
344                         } \
345                 } \
346         } \
351 void AgingClient::scratching(unsigned char **output_rows,
352         int color_model,
353         int w,
354         int h)
356         switch(color_model)
357         {
358                 case BC_RGB888:
359                         SCRATCHES(uint8_t, 3, 0);
360                         break;
362                 case BC_RGB_FLOAT:
363                         SCRATCHES(float, 3, 0);
364                         break;
366                 case BC_YUV888:
367                         SCRATCHES(uint8_t, 3, 0x80);
368                         break;
369                 
370                 case BC_RGBA_FLOAT:
371                         SCRATCHES(float, 4, 0);
372                         break;
374                 case BC_RGBA8888:
375                         SCRATCHES(uint8_t, 4, 0);
376                         break;
378                 case BC_YUVA8888:
379                         SCRATCHES(uint8_t, 4, 0x80);
380                         break;
381                 
382                 case BC_RGB161616:
383                         SCRATCHES(uint16_t, 3, 0);
384                         break;
386                 case BC_YUV161616:
387                         SCRATCHES(uint16_t, 3, 0x8000);
388                         break;
389                 
390                 case BC_RGBA16161616:
391                         SCRATCHES(uint16_t, 4, 0);
392                         break;
394                 case BC_YUVA16161616:
395                         SCRATCHES(uint16_t, 4, 0x8000);
396                         break;
397         }
402 #define PITS(type, components, luma, chroma) \
403 { \
404         int i, j, k; \
405         int pnum, size, pnumscale; \
406         int x, y; \
408         pnumscale = plugin->config.area_scale * 2; \
410         if(plugin->config.pits_interval)  \
411         { \
412                 pnum = pnumscale + (EffectTV::fastrand() % pnumscale); \
413                 plugin->config.pits_interval--; \
414         }  \
415         else \
416         { \
417                 pnum = EffectTV::fastrand() % pnumscale; \
418                 if((EffectTV::fastrand() & 0xf8000000) == 0)  \
419                 { \
420                         plugin->config.pits_interval = (EffectTV::fastrand() >> 28) + 20; \
421                 } \
422         } \
424         for(i = 0; i < pnum; i++)  \
425         { \
426                 x = EffectTV::fastrand() % (w - 1); \
427                 y = EffectTV::fastrand() % (h - 1); \
429                 size = EffectTV::fastrand() >> 28; \
431                 for(j = 0; j < size; j++)  \
432                 { \
433                         x = x + EffectTV::fastrand() % 3 - 1; \
434                         y = y + EffectTV::fastrand() % 3 - 1; \
436                         CLAMP(x, 0, w - 1); \
437                         CLAMP(y, 0, h - 1); \
438                         for(k = 0; k < (chroma ? 1 : 3); k++) \
439                         { \
440                                 ((type**)output_rows)[y][x * components + k] = luma; \
441                         } \
443             if(chroma) \
444                         { \
445                                 ((type**)output_rows)[y][x * components + 1] = chroma; \
446                                 ((type**)output_rows)[y][x * components + 2] = chroma; \
447                         } \
449                 } \
450         } \
458 void AgingClient::pits(unsigned char **output_rows,
459         int color_model,
460         int w,
461         int h)
463         switch(color_model)
464         {
465                 case BC_RGB888:
466                         PITS(uint8_t, 3, 0xc0, 0);
467                         break;
468                 case BC_RGB_FLOAT:
469                         PITS(float, 3, (float)0xc0 / 0xff, 0);
470                         break;
471                 case BC_YUV888:
472                         PITS(uint8_t, 3, 0xc0, 0x80);
473                         break;
474                 
475                 case BC_RGBA_FLOAT:
476                         PITS(float, 4, (float)0xc0 / 0xff, 0);
477                         break;
478                 case BC_RGBA8888:
479                         PITS(uint8_t, 4, 0xc0, 0);
480                         break;
481                 case BC_YUVA8888:
482                         PITS(uint8_t, 4, 0xc0, 0x80);
483                         break;
484                 
485                 case BC_RGB161616:
486                         PITS(uint16_t, 3, 0xc000, 0);
487                         break;
488                 case BC_YUV161616:
489                         PITS(uint16_t, 3, 0xc000, 0x8000);
490                         break;
491                 
492                 case BC_RGBA16161616:
493                         PITS(uint16_t, 4, 0xc000, 0);
494                         break;
495                 case BC_YUVA16161616:
496                         PITS(uint16_t, 4, 0xc000, 0x8000);
497                         break;
498         }
502 #define DUSTS(type, components, luma, chroma) \
503 { \
504         int i, j, k; \
505         int dnum; \
506         int d, len; \
507         int x, y; \
509         if(plugin->config.dust_interval == 0)  \
510         { \
511                 if((EffectTV::fastrand() & 0xf0000000) == 0)  \
512                 { \
513                         plugin->config.dust_interval = EffectTV::fastrand() >> 29; \
514                 } \
515                 return; \
516         } \
518         dnum = plugin->config.area_scale * 4 + (EffectTV::fastrand() >> 27); \
520         for(i = 0; i < dnum; i++)  \
521         { \
522                 x = EffectTV::fastrand() % w; \
523                 y = EffectTV::fastrand() % h; \
524                 d = EffectTV::fastrand() >> 29; \
525                 len = EffectTV::fastrand() % plugin->config.area_scale + 5; \
527                 for(j = 0; j < len; j++)  \
528                 { \
529                         CLAMP(x, 0, w - 1); \
530                         CLAMP(y, 0, h - 1); \
531                         for(k = 0; k < (chroma ? 1 : 3); k++) \
532                         { \
533                                 ((type**)output_rows)[y][x * components + k] = luma; \
534                         } \
536                         if(chroma) \
537                         { \
538                                 ((type**)output_rows)[y][x * components + 1] = chroma; \
539                                 ((type**)output_rows)[y][x * components + 2] = chroma; \
540                         } \
542                         y += AgingConfig::dy[d]; \
543                         x += AgingConfig::dx[d]; \
545                         if(x < 0 || x >= w) break; \
546                         if(y < 0 || y >= h) break; \
549                         d = (d + EffectTV::fastrand() % 3 - 1) & 7; \
550                 } \
551         } \
552         plugin->config.dust_interval--; \
558 void AgingClient::dusts(unsigned char **output_rows,
559         int color_model,
560         int w,
561         int h)
563         switch(color_model)
564         {
565                 case BC_RGB888:
566                         DUSTS(uint8_t, 3, 0x10, 0);
567                         break;
569                 case BC_RGB_FLOAT:
570                         DUSTS(float, 3, (float)0x10 / 0xff, 0);
571                         break;
573                 case BC_YUV888:
574                         DUSTS(uint8_t, 3, 0x10, 0x80);
575                         break;
576                 
577                 case BC_RGBA_FLOAT:
578                         DUSTS(float, 4, (float)0x10 / 0xff, 0);
579                         break;
581                 case BC_RGBA8888:
582                         DUSTS(uint8_t, 4, 0x10, 0);
583                         break;
585                 case BC_YUVA8888:
586                         DUSTS(uint8_t, 4, 0x10, 0x80);
587                         break;
588                 
589                 case BC_RGB161616:
590                         DUSTS(uint16_t, 3, 0x1000, 0);
591                         break;
593                 case BC_YUV161616:
594                         DUSTS(uint16_t, 3, 0x1000, 0x8000);
595                         break;
596                 
597                 case BC_RGBA16161616:
598                         DUSTS(uint16_t, 4, 0x1000, 0);
599                         break;
601                 case BC_YUVA16161616:
602                         DUSTS(uint16_t, 4, 0x1000, 0x8000);
603                         break;
604         }
609 void AgingClient::process_package(LoadPackage *package)
611 //printf("AgingClient::process_package 1\n");
612         AgingPackage *local_package = (AgingPackage*)package;
613         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
614         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
616 //printf("AgingClient::process_package 1\n");
617         if(plugin->config.colorage)
618                 coloraging(output_rows, 
619                         input_rows, 
620                         plugin->input_ptr->get_color_model(), 
621                         plugin->input_ptr->get_w(), 
622                         local_package->row2 - local_package->row1);
623 //printf("AgingClient::process_package 2\n");
624         if(plugin->config.scratch)
625                 scratching(output_rows, 
626                         plugin->input_ptr->get_color_model(), 
627                         plugin->input_ptr->get_w(), 
628                         local_package->row2 - local_package->row1);
629 //printf("AgingClient::process_package 3\n");
630         if(plugin->config.pits)
631                 pits(output_rows, 
632                         plugin->input_ptr->get_color_model(), 
633                         plugin->input_ptr->get_w(), 
634                         local_package->row2 - local_package->row1);
635 //printf("AgingClient::process_package 4 %d\n", plugin->config.dust);
636         if(plugin->config.dust)
637                 dusts(output_rows, 
638                         plugin->input_ptr->get_color_model(), 
639                         plugin->input_ptr->get_w(), 
640                         local_package->row2 - local_package->row1);
641 //printf("AgingClient::process_package 5\n");
646 AgingPackage::AgingPackage()