r123: Merged HEAD and TEST. New stuff shall be committed to HEAD from now on.
[cinelerra_cv/mob.git] / plugins / dot / dot.C
blobeef2dc5b322765a79a6f77ddb9a544d913bec712
1 #include "clip.h"
2 #include "colormodels.h"
3 #include "filexml.h"
4 #include "picon_png.h"
5 #include "dot.h"
6 #include "dotwindow.h"
7 #include "effecttv.h"
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
13 #include <libintl.h>
14 #define _(String) gettext(String)
15 #define gettext_noop(String) String
16 #define N_(String) gettext_noop (String)
18 PluginClient* new_plugin(PluginServer *server)
20         return new DotMain(server);
33 DotConfig::DotConfig()
35         dot_depth = 5;
36         dot_size = 8;
43 DotMain::DotMain(PluginServer *server)
44  : PluginVClient(server)
46         thread = 0;
47         defaults = 0;
48         pattern = 0;
49         sampx = 0;
50         sampy = 0;
51         effecttv = 0;
52         need_reconfigure = 1;
53         load_defaults();
56 DotMain::~DotMain()
58         if(thread)
59         {
60 // Set result to 0 to indicate a server side close
61                 thread->window->set_done(0);
62                 thread->completion.lock();
63                 delete thread;
64         }
65         
66         if(pattern) delete [] pattern;
67         if(sampx) delete [] sampx;
68         if(sampy) delete [] sampy;
69         if(effecttv)
70         {
71                 delete dot_server;
72                 delete effecttv;
73         }
74         save_defaults();
75         if(defaults) delete defaults;
78 char* DotMain::plugin_title() { return _("DotTV"); }
79 int DotMain::is_realtime() { return 1; }
81 NEW_PICON_MACRO(DotMain)
83 SHOW_GUI_MACRO(DotMain, DotThread)
85 SET_STRING_MACRO(DotMain)
87 RAISE_WINDOW_MACRO(DotMain)
90 int DotMain::load_defaults()
92         return 0;
95 int DotMain::save_defaults()
97         return 0;
100 void DotMain::load_configuration()
105 void DotMain::save_data(KeyFrame *keyframe)
109 void DotMain::read_data(KeyFrame *keyframe)
113 void DotMain::make_pattern()
115         int i, x, y, c;
116         int u, v;
117         double p, q, r;
118         uint32_t *pat;
120         for(i = 0; i < config.dot_max(); i++) 
121         {
122 /* Generated pattern is a quadrant of a disk. */
123                 pat = pattern + (i + 1) * dot_hsize * dot_hsize - 1;
125 //              r = (0.2 * i / config.dot_max() + 0.8) * dot_hsize;
126 //              r = r * r;
127                 r = ((double)i / config.dot_max()) * dot_hsize;
128                 r *= 5;
129 //printf("make_pattern %f\n", r);
131                 for(y = 0; y < dot_hsize; y++) 
132                 {
133                         for(x = 0; x < dot_hsize; x++) 
134                         {
135                                 c = 0;
136                                 for(u = 0; u < 4; u++) 
137                                 {
138                                         p = (double)u / 4.0 + y;
139                                         p = p * p;
141                                         for(v = 0; v < 4; v++) 
142                                         {
143                                                 q = (double)v / 4.0 + x;
145                                                 if(p + q * q < r) 
146                                                 {
147                                                         c++;
148                                                 }
149                                         }
150                                 }
153                                 c = (c > 15) ? 15 : c;
154 //printf("DotMain::make_pattern %d\n", c);
155                                 *pat-- = (c << 20) | (c << 12) | (c << 4);
156 /* The upper left part of a disk is needed, but generated pattern is a bottom
157  * right part. So I spin the pattern. */
158                         }
159                 }
160         }
163 void DotMain::init_sampxy_table()
165         int i, j;
167 // Need aspect ratio
168         j = dot_hsize;
169         for(i = 0; i < dots_width; i++) 
170         {
171                 sampx[i] = j;
172                 j += dot_size;
173         }
174         j = dot_hsize;
175         for(i = 0; i < dots_height; i++) 
176         {
177                 sampy[i] = j;
178                 j += dot_size;
179         }
183 void DotMain::reconfigure()
185         if(!effecttv)
186         {
187                 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
188                 dot_server = new DotServer(this, 1, 1);
189         }
191         dot_size = config.dot_size;
192         dot_size = dot_size & 0xfe;
193         dot_hsize = dot_size / 2;
194         dots_width = input_ptr->get_w() / dot_size;
195         dots_height = input_ptr->get_h() / dot_size;
196         pattern = new uint32_t[config.dot_max() * 
197                 dot_hsize * 
198                 dot_hsize];
199         sampx = new int[input_ptr->get_w()];
200         sampy = new int[input_ptr->get_h()];
201         
202         make_pattern();
203         
204         init_sampxy_table();
205         
206         
207         need_reconfigure = 0;
212 int DotMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
214         this->input_ptr = input_ptr;
215         this->output_ptr = output_ptr;
216         load_configuration();
217         if(need_reconfigure) reconfigure();
220         dot_server->process_packages();
222         return 0;
227 DotServer::DotServer(DotMain *plugin, int total_clients, int total_packages)
228  : LoadServer(total_clients, total_packages)
230         this->plugin = plugin;
234 LoadClient* DotServer::new_client() 
236         return new DotClient(this);
242 LoadPackage* DotServer::new_package() 
244         return new DotPackage; 
249 void DotServer::init_packages()
251         for(int i = 0; i < total_packages; i++)
252         {
253                 DotPackage *package = (DotPackage*)packages[i];
254                 package->row1 = plugin->input_ptr->get_h() / total_packages * i;
255                 package->row2 = package->row1 + plugin->input_ptr->get_h() / total_packages;
256                 if(i >= total_packages - 1)
257                         package->row2 = plugin->input_ptr->get_h();
258         }
268 DotClient::DotClient(DotServer *server)
269  : LoadClient(server)
271         this->plugin = server->plugin;
274 #define COPY_PIXEL(type, components, output, pattern, chroma_offset) \
275 { \
276         if(chroma_offset) \
277         { \
278                 if(sizeof(type) == 2) \
279                 { \
280                         output[0] = (pattern & 0xff0000) >> 8; \
281                         output[1] = chroma_offset; \
282                         output[2] = chroma_offset; \
283                         if(components > 3) output[3] = 0xffff; \
284                 } \
285                 else \
286                 { \
287                         output[0] = (pattern & 0xff0000) >> 16; \
288                         output[1] = chroma_offset; \
289                         output[2] = chroma_offset; \
290                         if(components > 3) output[3] = 0xff; \
291                 } \
292         } \
293         else \
294         { \
295                 if(sizeof(type) == 2) \
296                 { \
297                         output[0] = (pattern & 0xff0000) >> 8; \
298                         output[1] = (pattern & 0xff00); \
299                         output[2] = (pattern & 0xff) << 8; \
300                         if(components > 3) output[3] = 0xffff; \
301                 } \
302                 else \
303                 { \
304                         output[0] = (pattern & 0xff0000) >> 16; \
305                         output[1] = (pattern & 0xff00) >> 8; \
306                         output[2] = (pattern & 0xff); \
307                         if(components > 3) output[3] = 0xff; \
308                 } \
309         } \
312 #define DRAW_DOT(type, components, chroma_offset) \
313 { \
314         int x, y; \
315         uint32_t *pat; \
316         type *output; \
317         int y_total = 0; \
319         c = (c >> (8 - plugin->config.dot_depth)); \
320         pat = plugin->pattern + c * plugin->dot_hsize * plugin->dot_hsize; \
321         output = ((type**)output_rows)[0] + \
322                 yy *  \
323                 plugin->dot_size *  \
324                 plugin->input_ptr->get_w() * \
325                 components + \
326                 xx *  \
327                 plugin->dot_size * \
328                 components; \
330         for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++)  \
331         { \
332                 for(x = 0; x < plugin->dot_hsize; x++)  \
333                 { \
334                         COPY_PIXEL(type, components, output, *pat, chroma_offset); \
335                         output += components; \
336                         pat++; \
337                 } \
339                 pat -= 2; \
341                 for(x = 0; x < plugin->dot_hsize - 1; x++)  \
342                 { \
343                         COPY_PIXEL(type, components, output, *pat, chroma_offset); \
344                         output += components; \
345                         pat--; \
346                 } \
348                 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
350                 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
351                 pat += plugin->dot_hsize + 1; \
352                 y_total++; \
353         } \
355         pat -= plugin->dot_hsize * 2; \
357         for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++)  \
358         { \
359                 if(y < plugin->dot_hsize - 1) \
360                 { \
361                         for(x = 0; x < plugin->dot_hsize; x++)  \
362                         { \
363                                 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
364                                 output += components; \
365                                 pat++; \
366                         } \
368                         pat -= 2; \
370                         for(x = 0; x < plugin->dot_hsize - 1; x++)  \
371                         { \
372                                 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
373                                 output += components; \
374                                 pat--; \
375                         } \
377                         COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
379                         output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
380                         pat += -plugin->dot_hsize + 1; \
381                 } \
382                 else \
383                 { \
384                         for(x = 0; x < plugin->dot_hsize * 2; x++) \
385                         { \
386                                 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
387                                 output += components; \
388                         } \
389                 } \
391                 y_total++; \
393         } \
396 void DotClient::draw_dot(int xx, 
397         int yy, 
398         unsigned char c, 
399         unsigned char **output_rows,
400         int color_model)
402         switch(plugin->input_ptr->get_color_model())
403         {
404                 case BC_RGB888:
405                         DRAW_DOT(uint8_t, 3, 0x0);
406                         break;
408                 case BC_YUV888:
409                         DRAW_DOT(uint8_t, 3, 0x80);
410                         break;
412                 case BC_RGBA8888:
413                         DRAW_DOT(uint8_t, 4, 0x0);
414                         break;
416                 case BC_YUVA8888:
417                         DRAW_DOT(uint8_t, 4, 0x80);
418                         break;
420                 case BC_RGB161616:
421                         DRAW_DOT(uint16_t, 3, 0x0);
422                         break;
424                 case BC_YUV161616:
425                         DRAW_DOT(uint16_t, 3, 0x8000);
426                         break;
428                 case BC_RGBA16161616:
429                         DRAW_DOT(uint16_t, 4, 0x0);
430                         break;
431                 case BC_YUVA16161616:
432                         DRAW_DOT(uint16_t, 4, 0x8000);
433                         break;
434         }
437 #define RGB_TO_Y(type) \
438 { \
439         type *row_local = (type*)row; \
441         if(sizeof(type) == 2) \
442         { \
443                 i =  plugin->effecttv->RtoY[row_local[0] >> 8]; \
444                 i += plugin->effecttv->GtoY[row_local[1] >> 8]; \
445                 i += plugin->effecttv->BtoY[row_local[2] >> 8]; \
446         } \
447         else \
448         { \
449                 i =  plugin->effecttv->RtoY[row_local[0]]; \
450                 i += plugin->effecttv->GtoY[row_local[1]]; \
451                 i += plugin->effecttv->BtoY[row_local[2]]; \
452         } \
453 /*printf("RGB_TO_Y %d %d %d %d\n", plugin->effecttv->RtoY[row_local[0]], plugin->effecttv->GtoY[row_local[1]], plugin->effecttv->BtoY[row_local[2]], i);*/ \
456 unsigned char DotClient::RGBtoY(unsigned char *row, int color_model)
458         unsigned char i;
460         switch(color_model)
461         {
462                 case BC_RGB888:
463                 case BC_YUV888:
464                         RGB_TO_Y(uint8_t);
465                         break;
466                 case BC_RGBA8888:
467                 case BC_YUVA8888:
468                         RGB_TO_Y(uint8_t);
469                         break;
470                 case BC_RGB161616:
471                 case BC_YUV161616:
472                         RGB_TO_Y(uint16_t);
473                         break;
474                 case BC_RGBA16161616:
475                 case BC_YUVA16161616:
476                         RGB_TO_Y(uint16_t);
477                         break;
478         }
480         return i;
484 void DotClient::process_package(LoadPackage *package)
486         int x, y;
487         int sx, sy;
488         DotPackage *local_package = (DotPackage*)package;
489         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
490         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
491         int width = plugin->input_ptr->get_w();
492         int height = local_package->row2 - local_package->row1;
495         for(y = 0; y < plugin->dots_height; y++)
496         {
497                 sy = plugin->sampy[y];
498                 for(x = 0; x < plugin->dots_width; x++)
499                 {
500                         sx = plugin->sampx[x];
502 //printf("DotClient::process_package %d\n", 
503 //                                      RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()], 
504 //                                      plugin->input_ptr->get_color_model()));
505                         draw_dot(x, 
506                                 y,
507                                 RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()], 
508                                         plugin->input_ptr->get_color_model()),
509                                 output_rows,
510                                 plugin->input_ptr->get_color_model());
511                 }
512         }
517 DotPackage::DotPackage()