r1007: Make configure detect and work on amd64.
[cinelerra_cv/mob.git] / plugins / aging / aging.C
blobe15405d9c361bcc0254f56d58f40845a815f587a
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 < get_total_packages(); i++)
138         {
139                 AgingPackage *package = (AgingPackage*)get_package(i);
140                 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
141                 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
142         }
152 AgingClient::AgingClient(AgingServer *server)
153  : LoadClient(server)
155         this->plugin = server->plugin;
166 #define COLORAGE(type, components) \
167 { \
168         int a, b; \
169         int i, j, k; \
171         for(i = 0; i < h; i++) \
172         { \
173                 for(j = 0; j < w; j++) \
174                 { \
175                         for(k = 0; k < 3; k++) \
176                         { \
177                                 if(sizeof(type) == 4) \
178                                 { \
179                                         a = (int)(((type**)input_rows)[i][j * components + k] * 0xffff); \
180                                         CLAMP(a, 0, 0xffff); \
181                                 } \
182                                 else \
183                                         a = (int)((type**)input_rows)[i][j * components + k]; \
185                                 if(sizeof(type) == 4) \
186                                 { \
187                                         b = (a & 0xffff) >> 2; \
188                                         ((type**)output_rows)[i][j * components + k] = \
189                                                 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)) / 0xffff; \
190                                 } \
191                                 else \
192                                 if(sizeof(type) == 2) \
193                                 { \
194                                         b = (a & 0xffff) >> 2; \
195                                         ((type**)output_rows)[i][j * components + k] = \
196                                                 (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)); \
197                                 } \
198                                 else \
199                                 { \
200                                         b = (a & 0xff) >> 2; \
201                                         ((type**)output_rows)[i][j * components + k] =  \
202                                                 (type)(a - b + 0x18 + ((EffectTV::fastrand() >> 8) & 0x10)); \
203                                 } \
204                         } \
205                 } \
206         } \
209 void AgingClient::coloraging(unsigned char **output_rows, 
210         unsigned char **input_rows,
211         int color_model,
212         int w,
213         int h)
215         switch(color_model)
216         {
217                 case BC_RGB888:
218                 case BC_YUV888:
219                         COLORAGE(uint8_t, 3);
220                         break;
221                 
222                 case BC_RGB_FLOAT:
223                         COLORAGE(float, 3);
224                         break;
225                         
226                 case BC_RGBA_FLOAT:
227                         COLORAGE(float, 4);
228                         break;
229                         
230                 case BC_RGBA8888:
231                 case BC_YUVA8888:
232                         COLORAGE(uint8_t, 4);
233                         break;
234                 
235                 case BC_RGB161616:
236                 case BC_YUV161616:
237                         COLORAGE(uint16_t, 3);
238                         break;
239                 
240                 case BC_RGBA16161616:
241                 case BC_YUVA16161616:
242                         COLORAGE(uint16_t, 4);
243                         break;
244         }
252 #define SCRATCHES(type, components, chroma) \
253 { \
254         int i, j, y, y1, y2; \
255         type *p; \
256         int a, b; \
257         int w_256 = w * 256; \
259         for(i = 0; i < plugin->config.scratch_lines; i++) \
260         { \
261                 if(plugin->config.scratches[i].life)  \
262                 { \
263                         plugin->config.scratches[i].x = plugin->config.scratches[i].x + plugin->config.scratches[i].dx; \
264                         if(plugin->config.scratches[i].x < 0 || plugin->config.scratches[i].x > w_256)  \
265                         { \
266                                 plugin->config.scratches[i].life = 0; \
267                                 break; \
268                         } \
270                         p = (type*)output_rows[0] + \
271                                 (plugin->config.scratches[i].x >> 8) * \
272                                 components; \
274                         if(plugin->config.scratches[i].init)  \
275                         { \
276                                 y1 = plugin->config.scratches[i].init; \
277                                 plugin->config.scratches[i].init = 0; \
278                         }  \
279                         else  \
280                         { \
281                                 y1 = 0; \
282                         } \
284                         plugin->config.scratches[i].life--; \
285                         if(plugin->config.scratches[i].life)  \
286                         { \
287                                 y2 = h; \
288                         }  \
289                         else  \
290                         { \
291                                 y2 = EffectTV::fastrand() % h; \
292                         } \
294                         for(y = y1; y < y2; y++)  \
295                         { \
296                                 for(j = 0; j < (chroma ? 1 : 3); j++) \
297                                 { \
298                                         if(sizeof(type) == 4) \
299                                         { \
300                                                 int temp = (int)(p[j] * 0xffff); \
301                                                 CLAMP(temp, 0, 0xffff); \
302                                                 a = temp & 0xfeff; \
303                                                 a += 0x2000; \
304                                                 b = a & 0x10000; \
305                                                 p[j] = (type)(a | (b - (b >> 8))) / 0xffff; \
306                                         } \
307                                         else \
308                                         if(sizeof(type) == 2) \
309                                         { \
310                                                 int temp = (int)p[j]; \
311                                                 a = temp & 0xfeff; \
312                                                 a += 0x2000; \
313                                                 b = a & 0x10000; \
314                                                 p[j] = (type)(a | (b - (b >> 8))); \
315                                         } \
316                                         else \
317                                         { \
318                                                 int temp = (int)p[j]; \
319                                                 a = temp & 0xfe; \
320                                                 a += 0x20; \
321                                                 b = a & 0x100; \
322                                                 p[j] = (type)(a | (b - (b >> 8))); \
323                                         } \
324                                 } \
326                                 if(chroma) \
327                                 { \
328                                         p[1] = chroma; \
329                                         p[2] = chroma; \
330                                 } \
331                                 p += w * components; \
332                         } \
333                 }  \
334                 else  \
335                 { \
336                         if((EffectTV::fastrand() & 0xf0000000) == 0)  \
337                         { \
338                                 plugin->config.scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
339                                 plugin->config.scratches[i].x = EffectTV::fastrand() % (w_256); \
340                                 plugin->config.scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
341                                 plugin->config.scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
342                         } \
343                 } \
344         } \
349 void AgingClient::scratching(unsigned char **output_rows,
350         int color_model,
351         int w,
352         int h)
354         switch(color_model)
355         {
356                 case BC_RGB888:
357                         SCRATCHES(uint8_t, 3, 0);
358                         break;
360                 case BC_RGB_FLOAT:
361                         SCRATCHES(float, 3, 0);
362                         break;
364                 case BC_YUV888:
365                         SCRATCHES(uint8_t, 3, 0x80);
366                         break;
367                 
368                 case BC_RGBA_FLOAT:
369                         SCRATCHES(float, 4, 0);
370                         break;
372                 case BC_RGBA8888:
373                         SCRATCHES(uint8_t, 4, 0);
374                         break;
376                 case BC_YUVA8888:
377                         SCRATCHES(uint8_t, 4, 0x80);
378                         break;
379                 
380                 case BC_RGB161616:
381                         SCRATCHES(uint16_t, 3, 0);
382                         break;
384                 case BC_YUV161616:
385                         SCRATCHES(uint16_t, 3, 0x8000);
386                         break;
387                 
388                 case BC_RGBA16161616:
389                         SCRATCHES(uint16_t, 4, 0);
390                         break;
392                 case BC_YUVA16161616:
393                         SCRATCHES(uint16_t, 4, 0x8000);
394                         break;
395         }
400 #define PITS(type, components, luma, chroma) \
401 { \
402         int i, j, k; \
403         int pnum, size, pnumscale; \
404         int x, y; \
406         pnumscale = plugin->config.area_scale * 2; \
408         if(plugin->config.pits_interval)  \
409         { \
410                 pnum = pnumscale + (EffectTV::fastrand() % pnumscale); \
411                 plugin->config.pits_interval--; \
412         }  \
413         else \
414         { \
415                 pnum = EffectTV::fastrand() % pnumscale; \
416                 if((EffectTV::fastrand() & 0xf8000000) == 0)  \
417                 { \
418                         plugin->config.pits_interval = (EffectTV::fastrand() >> 28) + 20; \
419                 } \
420         } \
422         for(i = 0; i < pnum; i++)  \
423         { \
424                 x = EffectTV::fastrand() % (w - 1); \
425                 y = EffectTV::fastrand() % (h - 1); \
427                 size = EffectTV::fastrand() >> 28; \
429                 for(j = 0; j < size; j++)  \
430                 { \
431                         x = x + EffectTV::fastrand() % 3 - 1; \
432                         y = y + EffectTV::fastrand() % 3 - 1; \
434                         CLAMP(x, 0, w - 1); \
435                         CLAMP(y, 0, h - 1); \
436                         for(k = 0; k < (chroma ? 1 : 3); k++) \
437                         { \
438                                 ((type**)output_rows)[y][x * components + k] = luma; \
439                         } \
441             if(chroma) \
442                         { \
443                                 ((type**)output_rows)[y][x * components + 1] = chroma; \
444                                 ((type**)output_rows)[y][x * components + 2] = chroma; \
445                         } \
447                 } \
448         } \
456 void AgingClient::pits(unsigned char **output_rows,
457         int color_model,
458         int w,
459         int h)
461         switch(color_model)
462         {
463                 case BC_RGB888:
464                         PITS(uint8_t, 3, 0xc0, 0);
465                         break;
466                 case BC_RGB_FLOAT:
467                         PITS(float, 3, (float)0xc0 / 0xff, 0);
468                         break;
469                 case BC_YUV888:
470                         PITS(uint8_t, 3, 0xc0, 0x80);
471                         break;
472                 
473                 case BC_RGBA_FLOAT:
474                         PITS(float, 4, (float)0xc0 / 0xff, 0);
475                         break;
476                 case BC_RGBA8888:
477                         PITS(uint8_t, 4, 0xc0, 0);
478                         break;
479                 case BC_YUVA8888:
480                         PITS(uint8_t, 4, 0xc0, 0x80);
481                         break;
482                 
483                 case BC_RGB161616:
484                         PITS(uint16_t, 3, 0xc000, 0);
485                         break;
486                 case BC_YUV161616:
487                         PITS(uint16_t, 3, 0xc000, 0x8000);
488                         break;
489                 
490                 case BC_RGBA16161616:
491                         PITS(uint16_t, 4, 0xc000, 0);
492                         break;
493                 case BC_YUVA16161616:
494                         PITS(uint16_t, 4, 0xc000, 0x8000);
495                         break;
496         }
500 #define DUSTS(type, components, luma, chroma) \
501 { \
502         int i, j, k; \
503         int dnum; \
504         int d, len; \
505         int x, y; \
507         if(plugin->config.dust_interval == 0)  \
508         { \
509                 if((EffectTV::fastrand() & 0xf0000000) == 0)  \
510                 { \
511                         plugin->config.dust_interval = EffectTV::fastrand() >> 29; \
512                 } \
513                 return; \
514         } \
516         dnum = plugin->config.area_scale * 4 + (EffectTV::fastrand() >> 27); \
518         for(i = 0; i < dnum; i++)  \
519         { \
520                 x = EffectTV::fastrand() % w; \
521                 y = EffectTV::fastrand() % h; \
522                 d = EffectTV::fastrand() >> 29; \
523                 len = EffectTV::fastrand() % plugin->config.area_scale + 5; \
525                 for(j = 0; j < len; j++)  \
526                 { \
527                         CLAMP(x, 0, w - 1); \
528                         CLAMP(y, 0, h - 1); \
529                         for(k = 0; k < (chroma ? 1 : 3); k++) \
530                         { \
531                                 ((type**)output_rows)[y][x * components + k] = luma; \
532                         } \
534                         if(chroma) \
535                         { \
536                                 ((type**)output_rows)[y][x * components + 1] = chroma; \
537                                 ((type**)output_rows)[y][x * components + 2] = chroma; \
538                         } \
540                         y += AgingConfig::dy[d]; \
541                         x += AgingConfig::dx[d]; \
543                         if(x < 0 || x >= w) break; \
544                         if(y < 0 || y >= h) break; \
547                         d = (d + EffectTV::fastrand() % 3 - 1) & 7; \
548                 } \
549         } \
550         plugin->config.dust_interval--; \
556 void AgingClient::dusts(unsigned char **output_rows,
557         int color_model,
558         int w,
559         int h)
561         switch(color_model)
562         {
563                 case BC_RGB888:
564                         DUSTS(uint8_t, 3, 0x10, 0);
565                         break;
567                 case BC_RGB_FLOAT:
568                         DUSTS(float, 3, (float)0x10 / 0xff, 0);
569                         break;
571                 case BC_YUV888:
572                         DUSTS(uint8_t, 3, 0x10, 0x80);
573                         break;
574                 
575                 case BC_RGBA_FLOAT:
576                         DUSTS(float, 4, (float)0x10 / 0xff, 0);
577                         break;
579                 case BC_RGBA8888:
580                         DUSTS(uint8_t, 4, 0x10, 0);
581                         break;
583                 case BC_YUVA8888:
584                         DUSTS(uint8_t, 4, 0x10, 0x80);
585                         break;
586                 
587                 case BC_RGB161616:
588                         DUSTS(uint16_t, 3, 0x1000, 0);
589                         break;
591                 case BC_YUV161616:
592                         DUSTS(uint16_t, 3, 0x1000, 0x8000);
593                         break;
594                 
595                 case BC_RGBA16161616:
596                         DUSTS(uint16_t, 4, 0x1000, 0);
597                         break;
599                 case BC_YUVA16161616:
600                         DUSTS(uint16_t, 4, 0x1000, 0x8000);
601                         break;
602         }
607 void AgingClient::process_package(LoadPackage *package)
609 //printf("AgingClient::process_package 1\n");
610         AgingPackage *local_package = (AgingPackage*)package;
611         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
612         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
614 //printf("AgingClient::process_package 1\n");
615         if(plugin->config.colorage)
616                 coloraging(output_rows, 
617                         input_rows, 
618                         plugin->input_ptr->get_color_model(), 
619                         plugin->input_ptr->get_w(), 
620                         local_package->row2 - local_package->row1);
621 //printf("AgingClient::process_package 2\n");
622         if(plugin->config.scratch)
623                 scratching(output_rows, 
624                         plugin->input_ptr->get_color_model(), 
625                         plugin->input_ptr->get_w(), 
626                         local_package->row2 - local_package->row1);
627 //printf("AgingClient::process_package 3\n");
628         if(plugin->config.pits)
629                 pits(output_rows, 
630                         plugin->input_ptr->get_color_model(), 
631                         plugin->input_ptr->get_w(), 
632                         local_package->row2 - local_package->row1);
633 //printf("AgingClient::process_package 4 %d\n", plugin->config.dust);
634         if(plugin->config.dust)
635                 dusts(output_rows, 
636                         plugin->input_ptr->get_color_model(), 
637                         plugin->input_ptr->get_w(), 
638                         local_package->row2 - local_package->row1);
639 //printf("AgingClient::process_package 5\n");
644 AgingPackage::AgingPackage()