merged hv7 mod
[goodguy/history.git] / cinelerra-5.1 / plugins / burn / burn.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 "effecttv.h"
25 #include "filexml.h"
26 #include "language.h"
27 #include "bccolors.h"
28 #include "burn.h"
29 #include "burnwindow.h"
30
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <string.h>
34
35
36
37 REGISTER_PLUGIN(BurnMain)
38
39
40
41
42
43
44
45
46
47
48
49
50 BurnConfig::BurnConfig()
51 {
52         threshold = 50;
53         decay = 15;
54         recycle = 1.0;
55 }
56
57 BurnMain::BurnMain(PluginServer *server)
58  : PluginVClient(server)
59 {
60         input_ptr = 0;
61         output_ptr = 0;
62         burn_server = 0;
63         buffer = 0;
64         effecttv = 0;
65         yuv = new YUV;
66
67 }
68
69 BurnMain::~BurnMain()
70 {
71
72
73         if(buffer) delete [] buffer;
74         if(burn_server) delete burn_server;
75         if(effecttv) delete effecttv;
76         if(yuv) delete yuv;
77 }
78
79 const char* BurnMain::plugin_title() { return _("BurningTV"); }
80 int BurnMain::is_realtime() { return 1; }
81
82
83 NEW_WINDOW_MACRO(BurnMain, BurnWindow)
84
85
86 int BurnMain::load_configuration()
87 {
88         return 0;
89 //printf("BurnMain::load_configuration %d\n", source_position);
90 }
91
92
93 void BurnMain::save_data(KeyFrame *keyframe)
94 {
95 }
96
97 void BurnMain::read_data(KeyFrame *keyframe)
98 {
99 }
100
101
102
103 #define MAXCOLOR 120
104
105 void BurnMain::HSItoRGB(double H,
106         double S,
107         double I,
108         int *r,
109         int *g,
110         int *b,
111         int color_model)
112 {
113         double T, Rv, Gv, Bv;
114
115         T = H;
116         Rv = 1 + S * sin(T - 2 * M_PI / 3);
117         Gv = 1 + S * sin(T);
118         Bv = 1 + S * sin(T + 2  * M_PI / 3);
119         T = 255.999 * I / 2;
120
121         *r = (int)CLIP(Rv * T, 0, 255);
122         *g = (int)CLIP(Gv * T, 0, 255);
123         *b = (int)CLIP(Bv * T, 0, 255);
124 }
125
126
127 void BurnMain::make_palette(int color_model)
128 {
129         int i, r, g, b;
130
131         for(i = 0; i < MAXCOLOR; i++)
132         {
133                 HSItoRGB(4.6 - 1.5 * i / MAXCOLOR,
134                         (double)i / MAXCOLOR,
135                         (double)i / MAXCOLOR,
136                         &r,
137                         &g,
138                         &b,
139                         color_model);
140                 palette[0][i] = r;
141                 palette[1][i] = g;
142                 palette[2][i] = b;
143 //printf("BurnMain::make_palette %d %d %d %d\n", i, palette[0][i], palette[1][i], palette[2][i]);
144         }
145
146
147         for(i = MAXCOLOR; i < 256; i++)
148         {
149                 if(r < 255) r++;
150                 if(r < 255) r++;
151                 if(r < 255) r++;
152                 if(g < 255) g++;
153                 if(g < 255) g++;
154                 if(b < 255) b++;
155                 if(b < 255) b++;
156                 palette[0][i] = r;
157                 palette[1][i] = g;
158                 palette[2][i] = b;
159 //printf("BurnMain::make_palette %d %d %d %d\n", i, palette[0][i], palette[1][i], palette[2][i]);
160         }
161 }
162
163
164
165
166 int BurnMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
167 {
168         this->input_ptr = input_ptr;
169         this->output_ptr = output_ptr;
170
171         load_configuration();
172
173         if(!burn_server)
174         {
175                 effecttv = new EffectTV(input_ptr->get_w(), input_ptr->get_h());
176                 buffer = (unsigned char *)new unsigned char[input_ptr->get_w() * input_ptr->get_h()];
177                 make_palette(input_ptr->get_color_model());
178
179                 effecttv->image_set_threshold_y(config.threshold);
180                 total = 0;
181
182                 burn_server = new BurnServer(this, 1, 1);
183         }
184
185         if(total == 0)
186         {
187                 bzero(buffer, input_ptr->get_w() * input_ptr->get_h());
188                 effecttv->image_bgset_y(input_ptr);
189         }
190         burn_server->process_packages();
191
192         total++;
193 //      if(total >= config.recycle * project_frame_rate) total = 0;
194         return 0;
195 }
196
197
198
199 BurnServer::BurnServer(BurnMain *plugin, int total_clients, int total_packages)
200  : LoadServer(total_clients, total_packages)
201 {
202         this->plugin = plugin;
203 }
204
205
206 LoadClient* BurnServer::new_client()
207 {
208         return new BurnClient(this);
209 }
210
211
212
213
214 LoadPackage* BurnServer::new_package()
215 {
216         return new BurnPackage;
217 }
218
219
220
221 void BurnServer::init_packages()
222 {
223         for(int i = 0; i < get_total_packages(); i++)
224         {
225                 BurnPackage *package = (BurnPackage*)get_package(i);
226                 package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
227                 package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
228         }
229 }
230
231
232
233
234
235
236
237
238 BurnClient::BurnClient(BurnServer *server)
239  : LoadClient(server)
240 {
241         this->plugin = server->plugin;
242 }
243
244
245
246
247
248
249
250
251
252 #define BURN(type, components, is_yuv) \
253 { \
254         i = 1; \
255         type **rows = (type**)input_rows; \
256         for(y = 0; y < height; y++)  \
257         { \
258                 for(x = 1; x < width - 1; x++)  \
259                 { \
260                         if(sizeof(type) == 4) \
261                         { \
262                                 a1 = (int)(rows[0][i * components] * 0xff); \
263                                 a2 = (int)(rows[0][i * components + 1] * 0xff); \
264                                 a3 = (int)(rows[0][i * components + 2] * 0xff); \
265                                 CLAMP(a1, 0, 0xff); \
266                                 CLAMP(a2, 0, 0xff); \
267                                 CLAMP(a3, 0, 0xff); \
268                                 b1 = plugin->palette[0][plugin->buffer[i]]; \
269                                 b2 = plugin->palette[1][plugin->buffer[i]]; \
270                                 b3 = plugin->palette[2][plugin->buffer[i]]; \
271                                 a1 += b1; \
272                                 a2 += b2; \
273                                 a3 += b3; \
274                                 b1 = a1 & 0x100; \
275                                 b2 = a2 & 0x100; \
276                                 b3 = a3 & 0x100; \
277                                 rows[0][i * components] = (type)(a1 | (b1 - (b1 >> 8))) / 0xff; \
278                                 rows[0][i * components + 1] = (type)(a2 | (b2 - (b2 >> 8))) / 0xff; \
279                                 rows[0][i * components + 2] = (type)(a3 | (b3 - (b3 >> 8))) / 0xff; \
280                         } \
281                         else \
282                         if(sizeof(type) == 2) \
283                         { \
284                                 a1 = ((int)rows[0][i * components + 0]) >> 8; \
285                                 a2 = ((int)rows[0][i * components + 1]) >> 8; \
286                                 a3 = ((int)rows[0][i * components + 2]) >> 8; \
287                                 b1 = plugin->palette[0][plugin->buffer[i]]; \
288                                 b2 = plugin->palette[1][plugin->buffer[i]]; \
289                                 b3 = plugin->palette[2][plugin->buffer[i]]; \
290                                 if(is_yuv) plugin->yuv->yuv_to_rgb_8(a1, a2, a3); \
291                                 a1 += b1; \
292                                 a2 += b2; \
293                                 a3 += b3; \
294                                 b1 = a1 & 0x100; \
295                                 b2 = a2 & 0x100; \
296                                 b3 = a3 & 0x100; \
297                                 a1 = (a1 | (b1 - (b1 >> 8))); \
298                                 a2 = (a2 | (b2 - (b2 >> 8))); \
299                                 a3 = (a3 | (b3 - (b3 >> 8))); \
300                                 if(is_yuv) \
301                                 { \
302                                         CLAMP(a1, 0, 0xff); \
303                                         CLAMP(a2, 0, 0xff); \
304                                         CLAMP(a3, 0, 0xff); \
305                                         plugin->yuv->rgb_to_yuv_8(a1, a2, a3); \
306                                 } \
307                                 rows[0][i * components + 0] = a1 | (a1 << 8); \
308                                 rows[0][i * components + 1] = a2 | (a2 << 8); \
309                                 rows[0][i * components + 2] = a3 | (a3 << 8); \
310                         } \
311                         else \
312                         { \
313                                 a1 = (int)rows[0][i * components + 0]; \
314                                 a2 = (int)rows[0][i * components + 1]; \
315                                 a3 = (int)rows[0][i * components + 2]; \
316                                 b1 = plugin->palette[0][plugin->buffer[i]]; \
317                                 b2 = plugin->palette[1][plugin->buffer[i]]; \
318                                 b3 = plugin->palette[2][plugin->buffer[i]]; \
319                                 if(is_yuv) plugin->yuv->yuv_to_rgb_8(a1, a2, a3); \
320                                 a1 += b1; \
321                                 a2 += b2; \
322                                 a3 += b3; \
323                                 b1 = a1 & 0x100; \
324                                 b2 = a2 & 0x100; \
325                                 b3 = a3 & 0x100; \
326                                 a1 = (a1 | (b1 - (b1 >> 8))); \
327                                 a2 = (a2 | (b2 - (b2 >> 8))); \
328                                 a3 = (a3 | (b3 - (b3 >> 8))); \
329                                 if(is_yuv) \
330                                 { \
331                                         CLAMP(a1, 0, 0xff); \
332                                         CLAMP(a2, 0, 0xff); \
333                                         CLAMP(a3, 0, 0xff); \
334                                         plugin->yuv->rgb_to_yuv_8(a1, a2, a3); \
335                                 } \
336                                 rows[0][i * components + 0] = a1; \
337                                 rows[0][i * components + 1] = a2; \
338                                 rows[0][i * components + 2] = a3; \
339                         } \
340                         i++; \
341                 } \
342                 i += 2; \
343         } \
344 }
345
346
347
348
349 void BurnClient::process_package(LoadPackage *package)
350 {
351         BurnPackage *local_package = (BurnPackage*)package;
352         unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
353         //unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
354         int width = plugin->input_ptr->get_w();
355         int height = local_package->row2 - local_package->row1;
356         unsigned char *diff;
357         //int pitch = width * plugin->input_ptr->get_bytes_per_pixel();
358         int i, x, y;
359         int a1, a2, a3;
360         int b1, b2, b3;
361
362         diff = plugin->effecttv->image_bgsubtract_y(input_rows,
363                 plugin->input_ptr->get_color_model());
364
365         for(x = 1; x < width - 1; x++)
366         {
367                 unsigned int v = 0;
368                 for(y = 0; y < height - 1; y++)
369                 {
370                         unsigned int w = diff[y * width + x];
371                         plugin->buffer[y * width + x] |= v ^ w;
372                         v = w;
373                 }
374         }
375
376         for(x = 1; x < width - 1; x++)
377         {
378                 i = width + x;
379
380                 for(y = 1; y < height; y++)
381                 {
382                         int v = plugin->buffer[i];
383
384                         if(v < plugin->config.decay)
385                                 plugin->buffer[i - width] = 0;
386                         else
387                                 plugin->buffer[i - width + EffectTV::fastrand() % 3 - 1] =
388                                         v - (EffectTV::fastrand() & plugin->config.decay);
389
390                         i += width;
391                 }
392         }
393
394
395
396         switch(plugin->input_ptr->get_color_model())
397         {
398                 case BC_RGB888:
399                         BURN(uint8_t, 3, 0);
400                         break;
401                 case BC_YUV888:
402                         BURN(uint8_t, 3, 1);
403                         break;
404
405                 case BC_RGB_FLOAT:
406                         BURN(float, 3, 0);
407                         break;
408
409                 case BC_RGBA_FLOAT:
410                         BURN(float, 4, 0);
411                         break;
412
413                 case BC_RGBA8888:
414                         BURN(uint8_t, 4, 0);
415                         break;
416                 case BC_YUVA8888:
417                         BURN(uint8_t, 4, 1);
418                         break;
419
420                 case BC_RGB161616:
421                         BURN(uint16_t, 3, 0);
422                         break;
423                 case BC_YUV161616:
424                         BURN(uint16_t, 3, 1);
425                         break;
426
427                 case BC_RGBA16161616:
428                         BURN(uint16_t, 4, 0);
429                         break;
430                 case BC_YUVA16161616:
431                         BURN(uint16_t, 4, 1);
432                         break;
433         }
434
435
436 }
437
438
439
440 BurnPackage::BurnPackage()
441 {
442 }
443
444
445