5060efd21e37be5bb790b5397d92ae47927fb555
[goodguy/history.git] / cinelerra-5.1 / plugins / dot / dot.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "clip.h"
23 #include "bccmodels.h"
24 #include "filexml.h"
25 #include "dot.h"
26 #include "dotwindow.h"
27 #include "effecttv.h"
28 #include "language.h"
29
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33
34
35
36
37
38
39 REGISTER_PLUGIN(DotMain)
40
41
42
43
44
45
46
47 DotConfig::DotConfig()
48 {
49         dot_depth = 5;
50         dot_size = 8;
51 }
52
53
54
55
56
57 DotMain::DotMain(PluginServer *server)
58  : PluginVClient(server)
59 {
60         pattern = 0;
61         sampx = 0;
62         sampy = 0;
63         effecttv = 0;
64         need_reconfigure = 1;
65
66 }
67
68 DotMain::~DotMain()
69 {
70
71
72         if(pattern) delete [] pattern;
73         if(sampx) delete [] sampx;
74         if(sampy) delete [] sampy;
75         if(effecttv)
76         {
77                 delete dot_server;
78                 delete effecttv;
79         }
80 }
81
82 const char* DotMain::plugin_title() { return _("DotTV"); }
83 int DotMain::is_realtime() { return 1; }
84
85 NEW_WINDOW_MACRO(DotMain, DotWindow)
86
87
88
89 int DotMain::load_configuration()
90 {
91         return 0;
92 }
93
94
95 void DotMain::save_data(KeyFrame *keyframe)
96 {
97 }
98
99 void DotMain::read_data(KeyFrame *keyframe)
100 {
101 }
102
103 void DotMain::make_pattern()
104 {
105         int i, x, y, c;
106         int u, v;
107         double p, q, r;
108         uint32_t *pat;
109
110         for(i = 0; i < config.dot_max(); i++)
111         {
112 /* Generated pattern is a quadrant of a disk. */
113                 pat = pattern + (i + 1) * dot_hsize * dot_hsize - 1;
114
115 //              r = (0.2 * i / config.dot_max() + 0.8) * dot_hsize;
116 //              r = r * r;
117                 r = ((double)i / config.dot_max()) * dot_hsize;
118                 r *= 5;
119 //printf("make_pattern %f\n", r);
120
121                 for(y = 0; y < dot_hsize; y++)
122                 {
123                         for(x = 0; x < dot_hsize; x++)
124                         {
125                                 c = 0;
126                                 for(u = 0; u < 4; u++)
127                                 {
128                                         p = (double)u / 4.0 + y;
129                                         p = p * p;
130
131                                         for(v = 0; v < 4; v++)
132                                         {
133                                                 q = (double)v / 4.0 + x;
134
135                                                 if(p + q * q < r)
136                                                 {
137                                                         c++;
138                                                 }
139                                         }
140                                 }
141
142
143                                 c = (c > 15) ? 15 : c;
144 //printf("DotMain::make_pattern %d\n", c);
145                                 *pat-- = (c << 20) | (c << 12) | (c << 4);
146 /* The upper left part of a disk is needed, but generated pattern is a bottom
147  * right part. So I spin the pattern. */
148                         }
149                 }
150         }
151 }
152
153 void DotMain::init_sampxy_table()
154 {
155         int i, j;
156
157 // Need aspect ratio
158         j = dot_hsize;
159         for(i = 0; i < dots_width; i++)
160         {
161                 sampx[i] = j;
162                 j += dot_size;
163         }
164         j = dot_hsize;
165         for(i = 0; i < dots_height; i++)
166         {
167                 sampy[i] = j;
168                 j += dot_size;
169         }
170 }
171
172
173 void DotMain::reconfigure()
174 {
175         if(!effecttv)
176         {
177                 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
178                 dot_server = new DotServer(this, 1, 1);
179         }
180
181         dot_size = config.dot_size;
182         dot_size = dot_size & 0xfe;
183         dot_hsize = dot_size / 2;
184         dots_width = input_ptr->get_w() / dot_size;
185         dots_height = input_ptr->get_h() / dot_size;
186         pattern = new uint32_t[config.dot_max() *
187                 dot_hsize *
188                 dot_hsize];
189         sampx = new int[input_ptr->get_w()];
190         sampy = new int[input_ptr->get_h()];
191
192         make_pattern();
193
194         init_sampxy_table();
195
196
197         need_reconfigure = 0;
198 }
199
200
201
202 int DotMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
203 {
204         this->input_ptr = input_ptr;
205         this->output_ptr = output_ptr;
206         load_configuration();
207         if(need_reconfigure) reconfigure();
208
209
210         dot_server->process_packages();
211
212         return 0;
213 }
214
215
216
217 DotServer::DotServer(DotMain *plugin, int total_clients, int total_packages)
218  : LoadServer(total_clients, total_packages)
219 {
220         this->plugin = plugin;
221 }
222
223
224 LoadClient* DotServer::new_client()
225 {
226         return new DotClient(this);
227 }
228
229
230
231
232 LoadPackage* DotServer::new_package()
233 {
234         return new DotPackage;
235 }
236
237
238
239 void DotServer::init_packages()
240 {
241         for(int i = 0; i < get_total_packages(); i++)
242         {
243                 DotPackage *package = (DotPackage*)get_package(i);
244                 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
245                 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
246         }
247 }
248
249
250
251
252
253
254
255
256 DotClient::DotClient(DotServer *server)
257  : LoadClient(server)
258 {
259         this->plugin = server->plugin;
260 }
261
262 #define COPY_uint16_t_0x8000_PIXEL(components, output, pattern) \
263 { \
264         output[0] = (pattern & 0xff0000) >> 8; \
265         output[1] = output[2] = 0x8000; \
266         if(components > 3) output[3] = 0xffff; \
267 }
268 #define COPY_uint8_t_0x80_PIXEL(components, output, pattern) \
269 { \
270         output[0] = (pattern & 0xff0000) >> 16; \
271         output[1] = output[2] = 0x80; \
272         if(components > 3) output[3] = 0xff; \
273 }
274
275 #define COPY_float_0x0_PIXEL(components, output, pattern) \
276 { \
277         output[0] = (float)(pattern & 0xff0000) / 0xff0000; \
278         output[1] = (float)(pattern & 0xff00) / 0xff00; \
279         output[2] = (float)(pattern & 0xff) / 0xff; \
280         if(components > 3) output[3] = 1; \
281 }
282 #define COPY_uint16_t_0x0_PIXEL(components, output, pattern) \
283 { \
284         output[0] = (pattern & 0xff0000) >> 8; \
285         output[1] = (pattern & 0xff00); \
286         output[2] = (pattern & 0xff) << 8; \
287         if(components > 3) output[3] = 0xffff; \
288 }
289 #define COPY_uint8_t_0x0_PIXEL(components, output, pattern) \
290 { \
291         output[0] = (pattern & 0xff0000) >> 16; \
292         output[1] = (pattern & 0xff00) >> 8; \
293         output[2] = (pattern & 0xff); \
294         if(components > 3) output[3] = 0xff; \
295 }
296
297 #define DRAW_DOT(type, components, chroma) \
298 { \
299         int x, y; \
300         uint32_t *pat; \
301         type *output; \
302         int y_total = 0; \
303  \
304         c = (c >> (8 - plugin->config.dot_depth)); \
305         pat = plugin->pattern + c * plugin->dot_hsize * plugin->dot_hsize; \
306         output = ((type**)output_rows)[0] + \
307                 yy * plugin->dot_size * plugin->input_ptr->get_w() * components + \
308                 xx * plugin->dot_size * components; \
309  \
310         for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++)  \
311         { \
312                 for(x = 0; x < plugin->dot_hsize; x++) { \
313                         COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
314                         output += components; \
315                         pat++; \
316                 } \
317                 pat -= 2; \
318                 for(x = 0; x < plugin->dot_hsize - 1; x++) { \
319                         COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
320                         output += components; \
321                         pat--; \
322                 } \
323                 COPY_##type##_##chroma##_PIXEL(components, output, 0x00000000); \
324                 output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
325                 pat += plugin->dot_hsize + 1; \
326                 y_total++; \
327         } \
328  \
329         pat -= plugin->dot_hsize * 2; \
330  \
331         for(y = 0; y < plugin->dot_hsize && y_total < plugin->input_ptr->get_h(); y++)  \
332         { \
333                 if(y < plugin->dot_hsize - 1) { \
334                         for(x = 0; x < plugin->dot_hsize; x++) { \
335                                 COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
336                                 output += components; \
337                                 pat++; \
338                         } \
339                         pat -= 2; \
340                         for(x = 0; x < plugin->dot_hsize - 1; x++) { \
341                                 COPY_##type##_##chroma##_PIXEL(components, output, *pat); \
342                                 output += components; \
343                                 pat--; \
344                         } \
345                         COPY_##type##_##chroma##_PIXEL(components, output, 0x00000000); \
346                         output += components * (plugin->input_ptr->get_w() - plugin->dot_size + 1); \
347                         pat += -plugin->dot_hsize + 1; \
348                 } \
349                 else { \
350                         for(x = 0; x < plugin->dot_hsize * 2; x++) { \
351                                 COPY_##type##_##chroma##_PIXEL(components, output, 0x00000000); \
352                                 output += components; \
353                         } \
354                 } \
355  \
356                 y_total++; \
357         } \
358 }
359
360 void DotClient::draw_dot(int xx,
361         int yy,
362         unsigned char c,
363         unsigned char **output_rows,
364         int color_model)
365 {
366         switch(plugin->input_ptr->get_color_model())
367         {
368                 case BC_RGB888:
369                         DRAW_DOT(uint8_t, 3, 0x0);
370                         break;
371
372                 case BC_RGB_FLOAT:
373                         DRAW_DOT(float, 3, 0x0);
374                         break;
375
376                 case BC_YUV888:
377                         DRAW_DOT(uint8_t, 3, 0x80);
378                         break;
379
380                 case BC_RGBA_FLOAT:
381                         DRAW_DOT(float, 4, 0x0);
382                         break;
383
384                 case BC_RGBA8888:
385                         DRAW_DOT(uint8_t, 4, 0x0);
386                         break;
387
388                 case BC_YUVA8888:
389                         DRAW_DOT(uint8_t, 4, 0x80);
390                         break;
391
392                 case BC_RGB161616:
393                         DRAW_DOT(uint16_t, 3, 0x0);
394                         break;
395
396                 case BC_YUV161616:
397                         DRAW_DOT(uint16_t, 3, 0x8000);
398                         break;
399
400                 case BC_RGBA16161616:
401                         DRAW_DOT(uint16_t, 4, 0x0);
402                         break;
403                 case BC_YUVA16161616:
404                         DRAW_DOT(uint16_t, 4, 0x8000);
405                         break;
406         }
407 }
408
409 #define RGB_TO_Y(type, is_yuv) \
410 { \
411         type *row_local = (type*)row; \
412  \
413         if(sizeof(type) == 4) \
414         { \
415                 int r = (int)(row_local[0] * 0xff); \
416                 int g = (int)(row_local[0] * 0xff); \
417                 int b = (int)(row_local[0] * 0xff); \
418                 CLAMP(r, 0, 0xff); \
419                 CLAMP(g, 0, 0xff); \
420                 CLAMP(b, 0, 0xff); \
421                 result = plugin->effecttv->RtoY[r] + \
422                         plugin->effecttv->RtoY[g] + \
423                         plugin->effecttv->RtoY[b]; \
424         } \
425         else \
426         if(sizeof(type) == 2) \
427         { \
428                 if(is_yuv) \
429                         result = (int)row_local[0] >> 8; \
430                 else \
431                 { \
432                         result =  plugin->effecttv->RtoY[(int)row_local[0] >> 8]; \
433                         result += plugin->effecttv->GtoY[(int)row_local[1] >> 8]; \
434                         result += plugin->effecttv->BtoY[(int)row_local[2] >> 8]; \
435                 } \
436         } \
437         else \
438         { \
439                 if(is_yuv) \
440                         result = (int)row_local[0]; \
441                 else \
442                 { \
443                         result =  plugin->effecttv->RtoY[(int)row_local[0]]; \
444                         result += plugin->effecttv->GtoY[(int)row_local[1]]; \
445                         result += plugin->effecttv->BtoY[(int)row_local[2]]; \
446                 } \
447         } \
448 }
449
450 unsigned char DotClient::RGBtoY(unsigned char *row, int color_model)
451 {
452         unsigned char result = 0;
453
454         switch(color_model)
455         {
456                 case BC_RGB888:
457                 case BC_RGBA8888:
458                         RGB_TO_Y(uint8_t, 0);
459                         break;
460                 case BC_RGB_FLOAT:
461                 case BC_RGBA_FLOAT:
462                         RGB_TO_Y(float, 0);
463                         break;
464                 case BC_YUV888:
465                 case BC_YUVA8888:
466                         RGB_TO_Y(uint8_t, 1);
467                         break;
468                 case BC_RGB161616:
469                 case BC_RGBA16161616:
470                         RGB_TO_Y(uint16_t, 0);
471                         break;
472                 case BC_YUV161616:
473                 case BC_YUVA16161616:
474                         RGB_TO_Y(uint16_t, 1);
475                         break;
476         }
477
478         return result;
479 }
480
481
482 void DotClient::process_package(LoadPackage *package)
483 {
484         int x, y;
485         int sx, sy;
486         DotPackage *local_package = (DotPackage*)package;
487         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
488         unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
489         //int width = plugin->input_ptr->get_w();
490         //int height = local_package->row2 - local_package->row1;
491
492
493         for(y = 0; y < plugin->dots_height; y++)
494         {
495                 sy = plugin->sampy[y];
496                 for(x = 0; x < plugin->dots_width; x++)
497                 {
498                         sx = plugin->sampx[x];
499
500 //printf("DotClient::process_package %d\n",
501 //                                      RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()],
502 //                                      plugin->input_ptr->get_color_model()));
503                         draw_dot(x,
504                                 y,
505                                 RGBtoY(&input_rows[sy][sx * plugin->input_ptr->get_bytes_per_pixel()],
506                                         plugin->input_ptr->get_color_model()),
507                                 output_rows,
508                                 plugin->input_ptr->get_color_model());
509                 }
510         }
511 }
512
513
514
515 DotPackage::DotPackage()
516 {
517 }
518
519
520