Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / plugins / dot / dot.C
blob54239476d69c273038f55a52b5bd1b11410065cf
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"
8 #include "language.h"
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <string.h>
19 REGISTER_PLUGIN(DotMain)
27 DotConfig::DotConfig()
29         dot_depth = 5;
30         dot_size = 8;
37 DotMain::DotMain(PluginServer *server)
38  : PluginVClient(server)
40         pattern = 0;
41         sampx = 0;
42         sampy = 0;
43         effecttv = 0;
44         need_reconfigure = 1;
45         PLUGIN_CONSTRUCTOR_MACRO
48 DotMain::~DotMain()
50         PLUGIN_DESTRUCTOR_MACRO
51         
52         if(pattern) delete [] pattern;
53         if(sampx) delete [] sampx;
54         if(sampy) delete [] sampy;
55         if(effecttv)
56         {
57                 delete dot_server;
58                 delete effecttv;
59         }
62 char* DotMain::plugin_title() { return N_("DotTV"); }
63 int DotMain::is_realtime() { return 1; }
65 NEW_PICON_MACRO(DotMain)
67 SHOW_GUI_MACRO(DotMain, DotThread)
69 SET_STRING_MACRO(DotMain)
71 RAISE_WINDOW_MACRO(DotMain)
74 int DotMain::load_defaults()
76         return 0;
79 int DotMain::save_defaults()
81         return 0;
84 void DotMain::load_configuration()
89 void DotMain::save_data(KeyFrame *keyframe)
93 void DotMain::read_data(KeyFrame *keyframe)
97 void DotMain::make_pattern()
99         int i, x, y, c;
100         int u, v;
101         double p, q, r;
102         uint32_t *pat;
104         for(i = 0; i < config.dot_max(); i++) 
105         {
106 /* Generated pattern is a quadrant of a disk. */
107                 pat = pattern + (i + 1) * dot_hsize * dot_hsize - 1;
109 //              r = (0.2 * i / config.dot_max() + 0.8) * dot_hsize;
110 //              r = r * r;
111                 r = ((double)i / config.dot_max()) * dot_hsize;
112                 r *= 5;
113 //printf("make_pattern %f\n", r);
115                 for(y = 0; y < dot_hsize; y++) 
116                 {
117                         for(x = 0; x < dot_hsize; x++) 
118                         {
119                                 c = 0;
120                                 for(u = 0; u < 4; u++) 
121                                 {
122                                         p = (double)u / 4.0 + y;
123                                         p = p * p;
125                                         for(v = 0; v < 4; v++) 
126                                         {
127                                                 q = (double)v / 4.0 + x;
129                                                 if(p + q * q < r) 
130                                                 {
131                                                         c++;
132                                                 }
133                                         }
134                                 }
137                                 c = (c > 15) ? 15 : c;
138 //printf("DotMain::make_pattern %d\n", c);
139                                 *pat-- = (c << 20) | (c << 12) | (c << 4);
140 /* The upper left part of a disk is needed, but generated pattern is a bottom
141  * right part. So I spin the pattern. */
142                         }
143                 }
144         }
147 void DotMain::init_sampxy_table()
149         int i, j;
151 // Need aspect ratio
152         j = dot_hsize;
153         for(i = 0; i < dots_width; i++) 
154         {
155                 sampx[i] = j;
156                 j += dot_size;
157         }
158         j = dot_hsize;
159         for(i = 0; i < dots_height; i++) 
160         {
161                 sampy[i] = j;
162                 j += dot_size;
163         }
167 void DotMain::reconfigure()
169         if(!effecttv)
170         {
171                 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
172                 dot_server = new DotServer(this, 1, 1);
173         }
175         dot_size = config.dot_size;
176         dot_size = dot_size & 0xfe;
177         dot_hsize = dot_size / 2;
178         dots_width = input_ptr->get_w() / dot_size;
179         dots_height = input_ptr->get_h() / dot_size;
180         pattern = new uint32_t[config.dot_max() * 
181                 dot_hsize * 
182                 dot_hsize];
183         sampx = new int[input_ptr->get_w()];
184         sampy = new int[input_ptr->get_h()];
185         
186         make_pattern();
187         
188         init_sampxy_table();
189         
190         
191         need_reconfigure = 0;
196 int DotMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
198         this->input_ptr = input_ptr;
199         this->output_ptr = output_ptr;
200         load_configuration();
201         if(need_reconfigure) reconfigure();
204         dot_server->process_packages();
206         return 0;
211 DotServer::DotServer(DotMain *plugin, int total_clients, int total_packages)
212  : LoadServer(total_clients, total_packages)
214         this->plugin = plugin;
218 LoadClient* DotServer::new_client() 
220         return new DotClient(this);
226 LoadPackage* DotServer::new_package() 
228         return new DotPackage; 
233 void DotServer::init_packages()
235         for(int i = 0; i < get_total_packages(); i++)
236         {
237                 DotPackage *package = (DotPackage*)get_package(i);
238                 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
239                 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
240         }
250 DotClient::DotClient(DotServer *server)
251  : LoadClient(server)
253         this->plugin = server->plugin;
256 #define COPY_PIXEL(type, components, output, pattern, chroma_offset) \
257 { \
258         if(chroma_offset) \
259         { \
260                 if(sizeof(type) == 2) \
261                 { \
262                         output[0] = (pattern & 0xff0000) >> 8; \
263                         output[1] = chroma_offset; \
264                         output[2] = chroma_offset; \
265                         if(components > 3) output[3] = 0xffff; \
266                 } \
267                 else \
268                 { \
269                         output[0] = (pattern & 0xff0000) >> 16; \
270                         output[1] = chroma_offset; \
271                         output[2] = chroma_offset; \
272                         if(components > 3) output[3] = 0xff; \
273                 } \
274         } \
275         else \
276         { \
277                 if(sizeof(type) == 4) \
278                 { \
279                         output[0] = (type)(pattern & 0xff0000) / 0xff0000; \
280                         output[1] = (type)(pattern & 0xff00) / 0xff00; \
281                         output[2] = (type)(pattern & 0xff) / 0xff; \
282                         if(components > 3) output[3] = 1; \
283                 } \
284                 else \
285                 if(sizeof(type) == 2) \
286                 { \
287                         output[0] = (pattern & 0xff0000) >> 8; \
288                         output[1] = (pattern & 0xff00); \
289                         output[2] = (pattern & 0xff) << 8; \
290                         if(components > 3) output[3] = 0xffff; \
291                 } \
292                 else \
293                 { \
294                         output[0] = (pattern & 0xff0000) >> 16; \
295                         output[1] = (pattern & 0xff00) >> 8; \
296                         output[2] = (pattern & 0xff); \
297                         if(components > 3) output[3] = 0xff; \
298                 } \
299         } \
302 #define DRAW_DOT(type, components, chroma_offset) \
303 { \
304         int x, y; \
305         uint32_t *pat; \
306         type *output; \
307         int y_total = 0; \
309         c = (c >> (8 - plugin->config.dot_depth)); \
310         pat = plugin->pattern + c * plugin->dot_hsize * plugin->dot_hsize; \
311         output = ((type**)output_rows)[0] + \
312                 yy *  \
313                 plugin->dot_size *  \
314                 plugin->input_ptr->get_w() * \
315                 components + \
316                 xx *  \
317                 plugin->dot_size * \
318                 components; \
320         for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++)  \
321         { \
322                 for(x = 0; x < plugin->dot_hsize; x++)  \
323                 { \
324                         COPY_PIXEL(type, components, output, *pat, chroma_offset); \
325                         output += components; \
326                         pat++; \
327                 } \
329                 pat -= 2; \
331                 for(x = 0; x < plugin->dot_hsize - 1; x++)  \
332                 { \
333                         COPY_PIXEL(type, components, output, *pat, chroma_offset); \
334                         output += components; \
335                         pat--; \
336                 } \
338                 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
340                 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
341                 pat += plugin->dot_hsize + 1; \
342                 y_total++; \
343         } \
345         pat -= plugin->dot_hsize * 2; \
347         for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++)  \
348         { \
349                 if(y < plugin->dot_hsize - 1) \
350                 { \
351                         for(x = 0; x < plugin->dot_hsize; x++)  \
352                         { \
353                                 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
354                                 output += components; \
355                                 pat++; \
356                         } \
358                         pat -= 2; \
360                         for(x = 0; x < plugin->dot_hsize - 1; x++)  \
361                         { \
362                                 COPY_PIXEL(type, components, output, *pat, chroma_offset); \
363                                 output += components; \
364                                 pat--; \
365                         } \
367                         COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
369                         output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
370                         pat += -plugin->dot_hsize + 1; \
371                 } \
372                 else \
373                 { \
374                         for(x = 0; x < plugin->dot_hsize * 2; x++) \
375                         { \
376                                 COPY_PIXEL(type, components, output, 0x00000000, chroma_offset); \
377                                 output += components; \
378                         } \
379                 } \
381                 y_total++; \
383         } \
386 void DotClient::draw_dot(int xx, 
387         int yy, 
388         unsigned char c, 
389         unsigned char **output_rows,
390         int color_model)
392         switch(plugin->input_ptr->get_color_model())
393         {
394                 case BC_RGB888:
395                         DRAW_DOT(uint8_t, 3, 0x0);
396                         break;
398                 case BC_RGB_FLOAT:
399                         DRAW_DOT(float, 3, 0x0);
400                         break;
402                 case BC_YUV888:
403                         DRAW_DOT(uint8_t, 3, 0x80);
404                         break;
406                 case BC_RGBA_FLOAT:
407                         DRAW_DOT(float, 4, 0x0);
408                         break;
410                 case BC_RGBA8888:
411                         DRAW_DOT(uint8_t, 4, 0x0);
412                         break;
414                 case BC_YUVA8888:
415                         DRAW_DOT(uint8_t, 4, 0x80);
416                         break;
418                 case BC_RGB161616:
419                         DRAW_DOT(uint16_t, 3, 0x0);
420                         break;
422                 case BC_YUV161616:
423                         DRAW_DOT(uint16_t, 3, 0x8000);
424                         break;
426                 case BC_RGBA16161616:
427                         DRAW_DOT(uint16_t, 4, 0x0);
428                         break;
429                 case BC_YUVA16161616:
430                         DRAW_DOT(uint16_t, 4, 0x8000);
431                         break;
432         }
435 #define RGB_TO_Y(type, is_yuv) \
436 { \
437         type *row_local = (type*)row; \
439         if(sizeof(type) == 4) \
440         { \
441                 int r = (int)(row_local[0] * 0xff); \
442                 int g = (int)(row_local[0] * 0xff); \
443                 int b = (int)(row_local[0] * 0xff); \
444                 CLAMP(r, 0, 0xff); \
445                 CLAMP(g, 0, 0xff); \
446                 CLAMP(b, 0, 0xff); \
447                 i = plugin->effecttv->RtoY[r] + \
448                         plugin->effecttv->RtoY[g] + \
449                         plugin->effecttv->RtoY[b]; \
450         } \
451         else \
452         if(sizeof(type) == 2) \
453         { \
454                 if(is_yuv) \
455                         i = (int)row_local[0] >> 8; \
456                 else \
457                 { \
458                         i =  plugin->effecttv->RtoY[(int)row_local[0] >> 8]; \
459                         i += plugin->effecttv->GtoY[(int)row_local[1] >> 8]; \
460                         i += plugin->effecttv->BtoY[(int)row_local[2] >> 8]; \
461                 } \
462         } \
463         else \
464         { \
465                 if(is_yuv) \
466                         i = (int)row_local[0]; \
467                 else \
468                 { \
469                         i =  plugin->effecttv->RtoY[(int)row_local[0]]; \
470                         i += plugin->effecttv->GtoY[(int)row_local[1]]; \
471                         i += plugin->effecttv->BtoY[(int)row_local[2]]; \
472                 } \
473         } \
476 unsigned char DotClient::RGBtoY(unsigned char *row, int color_model)
478         unsigned char i;
480         switch(color_model)
481         {
482                 case BC_RGB888:
483                 case BC_RGBA8888:
484                         RGB_TO_Y(uint8_t, 0);
485                         break;
486                 case BC_RGB_FLOAT:
487                 case BC_RGBA_FLOAT:
488                         RGB_TO_Y(float, 0);
489                         break;
490                 case BC_YUV888:
491                 case BC_YUVA8888:
492                         RGB_TO_Y(uint8_t, 1);
493                         break;
494                 case BC_RGB161616:
495                 case BC_RGBA16161616:
496                         RGB_TO_Y(uint16_t, 0);
497                         break;
498                 case BC_YUV161616:
499                 case BC_YUVA16161616:
500                         RGB_TO_Y(uint16_t, 1);
501                         break;
502         }
504         return i;
508 void DotClient::process_package(LoadPackage *package)
510         int x, y;
511         int sx, sy;
512         DotPackage *local_package = (DotPackage*)package;
513         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
514         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
515         int width = plugin->input_ptr->get_w();
516         int height = local_package->row2 - local_package->row1;
519         for(y = 0; y < plugin->dots_height; y++)
520         {
521                 sy = plugin->sampy[y];
522                 for(x = 0; x < plugin->dots_width; x++)
523                 {
524                         sx = plugin->sampx[x];
526 //printf("DotClient::process_package %d\n", 
527 //                                      RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()], 
528 //                                      plugin->input_ptr->get_color_model()));
529                         draw_dot(x, 
530                                 y,
531                                 RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()], 
532                                         plugin->input_ptr->get_color_model()),
533                                 output_rows,
534                                 plugin->input_ptr->get_color_model());
535                 }
536         }
541 DotPackage::DotPackage()